⑴ c语言 象棋 走法 表示
语言象棋走法分三种:进、退、平。
象棋棋盘的九条竖线从左到右排列为:
红方:一、二、三、四、五、六、七、八、九
黑方:1、2、3、4、5、6、7、8、9
进:如马二进三,就是马从第二条竖线向前方(对方的方向)走到第三条竖线上。
退:如车一退一,就是把车向后(自己的方向)走一个格子;车一平二,就是向后走两个格子。 ——(兵、卒不可退)
平:如炮二平五,就是第二条线的炮走到第五条线上。 ——(马不可平)
如果两只马在同一条线上,那么可以说成前马进一、后马退三......
红棋与黑棋不同:如果红棋走炮二平五,黑棋也想走同样的棋路,就要写成炮2平5.
⑵ C语言编五子棋(二维数组),很简单
输入输出很简单的吧,主要是如何判断棋局结束。当前下子位置,共有八个方向,上对下,左对右,左上对右下,右上对左下。举上对下的例子,我向上和下两个方向同时搜索,并计数,当计数到5时,则棋局结束,只有当上下两个方向都不能继续搜索时,则停止。
⑶ C语言四皇后问题
//title:4皇后问题的回溯算法求解
//Demo: 1)回溯算法实现4皇后问题;2)难点:树形结构的表达;3)用线性容器表达树形结构,并实现树的扫描??降低了树实现的难度
//author: Liping Chen
//email: [email protected]
//published date: 20125-4-11
#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
using namespace std;
//定义4皇后棋局的数据结构及方法
typedef struct Queen4 {
int vals[16];
int nQueens;
int parent;
//默认构造函数
Queen4() {
for(int i = 0; i < 16; i++)
vals[i] = 0;
parent = 0;
nQueens = 0;
}
//构造函数1
Queen4(int nvals[16]) {
for(int i = 0; i < 16; i++)
vals[i] = nvals[i];
parent = 0;
nQueens = 0;
}
//找到当前布局中不为0的清镇位置
int getPosition() {
for(int i = 0; i < 16; i++)
if (vals[i] == 0) {
return i;
}
return -1;
}
//当设置皇竖正轮后位置时,标记水平、垂直和斜线位置掩码
void setQueen(int pos) {
int row, col;
vals[pos] = 1;
nQueens++;
row = pos / 4;
col = pos % 4;
for(int c = 1; c <= 3; c++) {
//右下
if (row + c < 4 && col + c < 4)
if (vals[(row + c) * 4 + (col + c)] == 0)
vals[(row + c) * 4 + (col + c)] = 2;
//左上
if (row - c >= 0 && col - c >= 0)
if (vals[(row - c) * 4 + (col - c)] == 0)
vals[(row - c) * 4 + (col - c)] = 2;
//左下
if (row + c < 4 && col - c >= 0)
if (vals[(row + c) * 4 + (col - c)] == 0)
vals[(row + c) * 4 + (col - c)] = 2;
//右上
if (row - c >= 0 && col + c >= 0)
if (vals[(row - c) * 4 + (col + c)] == 0)
vals[(row - c) * 4 + (col + c)] = 2;
//右水平
if (col + c < 4)
if (vals[row * 4 + (col + c)] == 0)
vals[row * 4 + (col + c)] = 2;
//左水平
if (col - c >= 0)
if (vals[row * 4 + (col - c)] == 0)
vals[row * 4 + (col - c)] = 2;
//下
if (row + c < 4)
if (vals[(row + c) * 4 + col] == 0)
vals[(row + c) * 4 + col] = 2;
//上
if (row - c >余信= 0)
if (vals[(row - c) * 4 + col] == 0)
vals[(row - c) * 4 + col] = 2;
}
}
//输出当前棋局
void output(int level) {
int cnt = 0;
char chars[100];
for(int k = 0; k < level; k++)
chars[k] = ' ';
chars[level] = '\0';
cout << chars << "Queen4=" << endl << chars;
for(int i = 0; i < 16; i++) {
cout << vals[i] << " ";
cnt++;
if (cnt % 4 == 0) cout << endl << chars;
}
}
//递归调用输出历史棋局
void outputHist(vector<Queen4>& tr) {
if (parent)
tr[parent].outputHist(tr);
output(0);
}
//由棋的当前布局产生下一布局
void reproce(vector<Queen4>& tr, int pos) {
int nvals[16];
bool inserted;
//思考:为什么要使用nvals
for(int i = 0; i < 16; i++)
nvals[i] = vals[i];
for(int i = 0; i < 16; i++) {
if (nvals[i] == 0) {
nvals[i] = 1;
//新结果加入容器
Queen4 q(tr[pos].vals);
q.setQueen(i);
q.parent = pos;
tr.push_back(q);
}
}
}
}Queen4;
//程序主函数
int main() {
Queen4 q0; //调用默认构造函数
vector<Queen4> tr; //向量容器??作用相当于队列,可以向期中添加新的棋盘布局
int levels[1024] = {0}; //记录每层的孩子数量??用于分层
tr.push_back(q0); //将初始棋盘加入容器
int oldn = 0, newn = 1, level = 0; //存储变量
//让根节点产生新孩子,并把新孩子加入容器
//若不再产生新孩子了,则认为已找到答案
//那么,最底层的就是答案(需要记录每层所产生的孩子数)
while(newn != oldn) {
//让最后的孩子再产生新孩子
for(int i = oldn; i < newn; i++) tr[i].reproce(tr, i);
//更新老孩子和新孩子的数量
oldn = newn;
levels[++level] = newn;
newn = tr.size();
}
oldn = 1;
//输出4皇后问题共有多少种解法
for(int i = levels[level-1]; i < levels[level]; i++) {
cout << "4皇后放置走法:" << oldn++ << endl;
tr[i].outputHist(tr);
}
return 0;
}
⑷ 求八皇后问题C语言源代码!急!
/*
* File: queen.c
* Description: 求 8 皇后问题回溯算法
* Created: 2001/11/12
* Author: Justin Hou [mailto:[email protected]]
*/
#include <stdio.h>
#define DelayTime 20000 /* 显示棋局时间 */
#define TopX 10 /* 棋盘左上角 x 坐标 */
#define TopY 5 /* 棋盘左上角 y 坐标 */
int N = 8; /* 皇后数量 */
int a[8], b[15], c[15];
/*
* a[col-1] 记录第 col 列有无皇后, 1 表示有。
* b[row+col-2] 记录从左上数第 row+col-1 条斜率为 1 的线上有无皇后。
* c[row-col+7] 记录从右上数第 row-col+8 条斜率为 -1 的线上有无皇后。
*/
int Num = 0;
int row;
void BackTrack (int row)
{
int col; /* 局部变量 */
for (col=1; col<=N; col++)
{
if (a[col-1] + b[row+col-2] + c[row-col+N-1] == 0)
{
a[col-1] = 1; /* 更改数据 */
b[row+col-2] = 1;
c[row-col+N-1] = 1;
gotoxy(col*2 + TopX, row + TopY); /* 画皇后 */
putch('Q');
if (row < N)
{
BackTrack (row + 1);
}
else
{
Num++; /* 递归终点 */
gotoxy(40, 9);
printf("Num: %d ", Num);
delay(DelayTime);
}
a[col-1] = 0; /* 清空数据 */
b[row+col-2] = 0;
c[row-col+N-1] = 0;
gotoxy(col*2 + TopX, row + TopY); /* 清除图象 */
putch('.');
}/* end if */
}/* end for */
}/* end function BackTrack */
void main()
{
int i, j;
clrscr();
gotoxy(1, 10); /* 要求用户输入皇后数量 */
printf("Input the number of queen: ");
while(N <= 0 || N > 14)
{
scanf("%d", &N);
if(N > 14) printf("Two huge number, input again:");
if(N <= 0) printf("Can's smaller than 1, again:");
}
clrscr();
for(i=1; i<=N; i++) /* 画棋盘(Chessboard) */
{
for(j=1; j<=N; j++)
{
gotoxy(i*2 + TopX, j + TopY);
putch('.');
}
}
BackTrack(1); /* 开始回溯算法 */
gotoxy(12, 17); /* 显示最后结果 */
printf ("There are %d kinds of solution.\n", Num);
getch();
}
⑸ 用C语言在linux下编写一个五子棋程序!
五子棋的核心算法
五子棋是一种受大众广泛喜爱的游戏,其规则简单,变化多端,非常富有趣味性和消遣性。这里设计和实现了一个人机对下的五子棋程序,采用了博弈树的方法,应用了剪枝和最大最小树原理进行搜索发现最好的下子位置。介绍五子棋程序的数据结构、评分规则、胜负判断方法和搜索算法过程。
一、相关的数据结构
关于盘面情况的表示,以链表形式表示当前盘面的情况,目的是可以允许用户进行悔棋、回退等操作。
CList StepList;
其中Step结构的表示为:
struct Step
{
int m; //m,n表示两个坐标值
int n;
char side; //side表示下子方
};
以数组形式保存当前盘面的情况,
目的是为了在显示当前盘面情况时使用:
char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];
其中FIVE_MAX_LINE表示盘面最大的行数。
同时由于需要在递归搜索的过程中考虑时间和空间有效性,只找出就当前情况来说相对比较好的几个盘面,而不是对所有的可下子的位置都进行搜索,这里用变量CountList来表示当前搜索中可以选择的所有新的盘面情况对象的集合:
CList CountList;
其中类CBoardSituiton为:
class CBoardSituation
{
CList StepList; //每一步的列表
char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];
struct Step machineStep; //机器所下的那一步
double value; //该种盘面状态所得到的分数
}
二、评分规则
对于下子的重要性评分,需要从六个位置来考虑当前棋局的情况,分别为:-,¦,/,\,//,\\
实际上需要考虑在这六个位置上某一方所形成的子的布局的情况,对于在还没有子的地方落子以后的当前局面的评分,主要是为了说明在这个地方下子的重要性程度,设定了一个简单的规则来表示当前棋面对机器方的分数。
基本的规则如下:
判断是否能成5, 如果是机器方的话给予100000分,如果是人方的话给予-100000 分;
判断是否能成活4或者是双死4或者是死4活3,如果是机器方的话给予10000分,如果是人方的话给予-10000分;
判断是否已成双活3,如果是机器方的话给予5000分,如果是人方的话给予-5000 分;
判断是否成死3活3,如果是机器方的话给予1000分,如果是人方的话给予-1000 分;
判断是否能成死4,如果是机器方的话给予500分,如果是人方的话给予-500分;
判断是否能成单活3,如果是机器方的话给予200分,如果是人方的话给予-200分;
判断是否已成双活2,如果是机器方的话给予100分,如果是人方的话给予-100分;
判断是否能成死3,如果是机器方的话给予50分,如果是人方的话给予-50分;
判断是否能成双活2,如果是机器方的话给予10分,如果是人方的话给予-10分;
判断是否能成活2,如果是机器方的话给予5分,如果是人方的话给予-5分;
判断是否能成死2,如果是机器方的话给予3分,如果是人方的话给予-3分。
实际上对当前的局面按照上面的规则的顺序进行比较,如果满足某一条规则的话,就给该局面打分并保存,然后退出规则的匹配。注意这里的规则是根据一般的下棋规律的一个总结,在实际运行的时候,用户可以添加规则和对评分机制加以修正。
三、胜负判断
实际上,是根据当前最后一个落子的情况来判断胜负的。实际上需要从四个位置判断,以该子为出发点的水平,竖直和两条分别为 45度角和135度角的线,目的是看在这四个方向是否最后落子的一方构成连续五个的棋子,如果是的话,就表示该盘棋局已经分出胜负。具体见下面的图示:
四、搜索算法实现描述
注意下面的核心的算法中的变量currentBoardSituation,表示当前机器最新的盘面情况, CountList表示第一层子节点可以选择的较好的盘面的集合。核心的算法如下:
void MainDealFunction()
{
value=-MAXINT; //对初始根节点的value赋值
CalSeveralGoodPlace(currentBoardSituation,CountList);
//该函数是根据当前的盘面情况来比较得到比较好的可以考虑的几个盘面的情况,可以根据实际的得分情况选取分数比较高的几个盘面,也就是说在第一层节点选择的时候采用贪婪算法,直接找出相对分数比较高的几个形成第一层节点,目的是为了提高搜索速度和防止堆栈溢出。
pos=CountList.GetHeadPosition();
CBoardSituation* pBoard;
for(i=0;ivalue=Search(pBoard,min,value,0);
Value=Select(value,pBoard->value,max);
//取value和pBoard->value中大的赋给根节点
}
for(i=0;ivalue)
//找出那一个得到最高分的盘面
{
currentBoardSituation=pBoard;
PlayerMode=min; //当前下子方改为人
Break;
}
}
其中对于Search函数的表示如下:实际上核心的算法是一个剪枝过程,其中在这个搜索过程中相关的四个参数为:(1)当前棋局情况;(2)当前的下子方,可以是机器(max)或者是人(min);(3)父节点的值oldValue;(4)当前的搜索深度depth。
double Search(CBoardSituation&
board,int mode,double oldvalue,int depth)
{
CList m_DeepList;
if(deptholdvalue))== TRUE)
{
if(mode==max)
value=select(value,search(successor
Board,min,value,depth+1),max);
else
value=select(value,search(successor
Board,max,value,depth+1),min);
}
return value;
}
else
{
if ( goal(board)<>0)
//这里goal(board)<>0表示已经可以分出胜负
return goal(board);
else
return evlation(board);
}
}
注意这里的goal(board)函数是用来判断当前盘面是否可以分出胜负,而evlation(board)是对当前的盘面从机器的角度进行打分。
下面是Select函数的介绍,这个函数的主要目的是根据 PlayerMode情况,即是机器还是用户来返回节点的应有的值。
double Select(double a,double b,int mode)
{
if(a>b && mode==max)¦¦ (a< b && mode==min)
return a;
else
return b;
}
五、小结
在Windows操作系统下,用VC++实现了这个人机对战的五子棋程序。和国内许多只是采用规则或者只是采用简单递归而没有剪枝的那些程序相比,在智力上和时间有效性上都要好于这些程序。同时所讨论的方法和设计过程为用户设计其他的游戏(如象棋和围棋等)提供了一个参考。
参考资料:http://www.3800hk.com/Article/cxsj/vc/jdsfvc/2005-08-06/Article_33695.html
⑹ 怎样用C语言编五子棋
任何一种棋类游戏其关键是对当前棋局是否有正确的评分,评分越准确则电脑的AI越高。五子棋游戏也是如此,但在打分之前,我们先扫描
整个棋盘,把每个空位从八个方向上的棋型填入数组gStyle(2, 15, 15, 8, 2),其中第一个下标为1时表示黑棋,为2时表示白棋,第二和第三
个下标表示(x,y),第四个下标表示8个方向,最后一个下标为局大世1时表示棋子数,为2时表示空格数,如:
gStyle(1,2,2,1,1)=3表示与坐标(2,2)在第1个方向上相邻的黑棋棋子数为3
gstyle(1,2,2,1,2)=4表示与坐标(2,2)在第1个方向上的最近的空格数为4
在定义方向时,也应该注意一定的技巧,表示两个相反的方向的数应该差4,在程序中我是这样定义的:
Const DIR_UP = 1
Const DIR_UPRIGHT = 2
Const DIR_RIGHT = 3
Const DIR_RIGHTDOWN = 4
Const DIR_DOWN = 5
Const DIR_DOWNLEFT = 6
Const DIR_LEFT = 7
Const DIR_LEFTUP = 8
这样我们前四个方向可以通过加四得到另一个方向的值。如果你还是不太明白,请看下面的图:
---------
---------
---oo----
-ox*xx---
---------
---------
图中的*点从标为(4,4),(打*的位置是空位),则:
gStyle(2,4,4,1,1)=1在(4,4)点相邻的上方白棋数为1
gStyle(2,4,4,1,2)=2在(4,4)点的上方距上方白棋最近的空格数为2
gStyle(1,4,4,3,1)=2在(4,4)点相邻的右方黑棋数为2
gStyle(1,4,4,3,2)=1在(4,4)点的右方距右方黑棋最近的空格数为3
...
一旦把所有空点的棋型值填完,我们很容易地得出黑棋水平方向上点(4,4)的价值,由一个冲桐肢1(我把有界的棋称为冲)和活2(两边无界的
棋称为活)组成的。对于而白棋在垂直方向上点(4,4)的价值是一个活1,而在/方向也是活1所以,只要我们把该点的对于黑棋和白棋的价值算出
来,然后我们就取棋盘上各个空点的这两个值的和的最大一点作为下棋的点。然而,对各种棋型应该取什么值呢?我们可以先作如下假设:
Fn 表示先手n个棋子的活棋型,如:F4表示先手活四
Fn'表示先手n个棋子的冲棋型,如:F4'表示先手冲四
Ln 表示后手n个棋子的活棋型,如:L3表示后手活三
Ln'表示后手n个棋子的冲棋型,如:L3'表示后手冲三
.
.
.
根据在一行中的棋型分析,得到如下关系:
L1'<=F1'<L2'<=F2'<=L1<F1<L2<F2<L3'<=F3'<L4'<F4'=F4
从这个关系包含了进攻和防守的关系(当然,这个关系是由我定的,你可以自己定义这些关系)。对这些关系再进一步细化,如在仿郑一个可下
棋的点,其四个方向上都有活三,也比不上一个冲四,所以我们可以又得到4*F3<L4'这个关系,同样,我们还可以得到其它的关系,如:4*F2<L3、4*L3<F3...,这些的关系由于你的定法和我的定法制可能不一样,这样计算机的AI也就不一样,最后我们把分值最小的L1'值定为1,则我们就得
到了下面各种棋型的分值,由C语言表示为:
F[2][5]={{0,2,5,50,16000},{0,10,30,750,16000}};
L[2][5]={{0,1,5,50,3750},{0,10,30,150,4000}};
F数组表示先手,第一个下标为0时表示冲型,第二个下标表示棋子数,则F2'对应F[0][2]L数组表示后手,第一个下标为0时表示冲型,第二
个下标表示棋子数,则L2对应F[1][2]Ok,棋型的分值关系确定好了以后,我们把每一个可下点的四个方向的棋型值相加(包括先手和后手的分
值),最后选择一个最大值,并把这一点作为计算机要下的点就OK了:)。
后话:
1、得到最大值也许不止一个点,但在我的程序中只选择第一个最大点,当然你可以用于个随机数来决定
选择那一个最大值点,也可以对这些最大值点再作进一步的分析。
2、在这个算法中我只考虑了周围有棋子的点,而其它点我没有考虑。
3、可以再更进一步,用这个算法来预测以后的几步棋,再选择预测值最好的一步,这样电脑的AI就更高了
4、这个算法没有考虑黑棋的禁手(双3、双四和多于五子的连棋)。因为在平时我下的五子棋是没有这些
禁手的。
⑺ 小主教问题 求解 用C语言哈~谢谢了
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
char n[3]={'0','0'};/*用于记录第几组解*/
int a[8],b[15],c[24],i;
int h[8]={127,177,227,277,327,377,427,477};/*每个皇后的行坐标*/
int l[8]={252,217,182,147,112,77,42,7}; /*每个皇后的列坐启卜标*/
void *arrow;
void try(int i)
{int j;
for (j=1;j<=8;j++)
if (a[j-1]+b[i+j-2]+c[i-j+7]==3) /*如果第i列第j行为空*/
{a[j-1]=0;b[i+j-2]=0;c[i-j+7]=0;/*占轿旁销用第i列第j行*/
putimage(h[i-1],l[j-1],arrow,COPY_PUT);/*显示皇后图形*/
delay(500);/*延时*/
if(i<8) try(i+1);
else /*输出一组解*/
{n[1]++;if (n[1]>'9') {n[0]++;n[1]='0';}
bar(260,300,390,340);/*显示第n组解*/
outtextxy(275,300,n);
delay(3000);
}
a[j-1]=1;b[i+j-2]=1;c[i-j+7]=1;
putimage(h[i-1],l[j-1],arrow,XOR_PUT);/*消去皇后,继续寻找下一组解*/
delay(500);
}}
int main(void)
{int gdrive=DETECT,gmode,errorcode;
unsigned int size;
initgraph(&gdrive,&gmode,"");
errorcode=graphresult();
if (errorcode!=grOk)
{printf("Graphics error\n");exit(1);}
rectangle(50,5,100,40);
rectangle(60,25,90,33);
/* 画皇冠 */
line(60,28,90,28);line(60,25,55,15);
line(55,15,68,25);line(68,25,68,10);
line(68,10,75,25);line(75,25,82,10);
line(82,10,82,25);line(82,25,95,15);
line(95,15,90,25);
size=imagesize(52,7,98,38); arrow=malloc(size);
getimage(52,7,98,38,arrow); /* 把皇冠保存闭游到缓冲区 */
clearviewport();
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4);
setusercharsize(3, 1, 1, 1);
setfillstyle(1,4);
for (i=0;i<=7;i++) a=1;
for (i=0;i<=14;i++) b=1;
for (i=0;i<=23;i++) c=1;
for (i=0;i<=8;i++) line(125,i*35+5,525,i*35+5); /* 画棋盘 */
for (i=0;i<=8;i++) line(125+i*50,5,125+i*50,285);
try(1); /* 调用递归函数 */
delay(3000);
closegraph();
free(arrow);
}
⑻ c语言 n皇后 求高手
八皇后问题各种语言版本:
http://ke..com/view/698719.htm
#include<iostream.h>
const int n = 15 ; //15皇后问题.改动n可变成N皇后问题
const int n_sub = n - 1 ;
int queen[n] ; //N个棋子.N对应每一列,如n=0的棋子只下在0列,1下1....类推
bool row[n] ; //棋局的每一行是否有棋,有则为1,无为0 ;
bool passive[2*n-1] ; //斜率为1的斜线方向上是不是有皇后
bool negative[2*n-1] ; //斜率为负1的斜线方向上是不是有皇后.
//之所以用全局变量,因全局数组元素值自动为0
int main()
{
int cur = 0 ;//游标,当前移动的棋子(哪一列的棋子)
bool flag = false ; //当前棋子位置是否合法
queen[0] = -1 ; //第0列棋子准备,因一开始移动的就是第0列棋子
int count = 0 ; //一共有多少种下法 ;
cout<<"============================Starting============================="<<endl ;
while(cur>=0)
{
while(cur>=0 && queen[cur]<n && !flag) //当还不确定当前位置是否可下
{
queen[cur]++ ;
// cout<<"第"<<cur<<"列棋子开始走在第"<<queen[cur]<<"行"<<endl ;
// cin.get() ;
if(queen[cur] >= n) { //如果当前列已经下完(找不到合法位置)
// cout<<"当前行是非法行,当前列棋子走完,没有合法位置,回溯上一列棋子"<<endl ;
// cin.get() ;
queen[cur] = -1 ; //当前列棋子置于准备状态
cur-- ; //回溯到上一列的棋子
if(cur>=0) {
row[queen[cur]] = false ;
passive[queen[cur] + cur] = false ;
negative[n_sub + cur - queen[cur]] = false ;
}
//由于要移下一步,所以回溯棋子原位置所在行应该没有棋子啦.置row[]为false
//并且棋子对应的斜线的标志位passive[cur]和negative[cur]也应该要设为false ;
}
else {
//先判断棋子所在行没有棋子
if(row[queen[cur]] == false) { //当前行没有棋子
// cout<<"棋子"<<cur<<"所在行没有其他棋子,正在检查斜线"<<endl ;
flag = true ; // 暂设为true,或与之前棋子斜交,则再设为false ;
//以下检查当前棋子是否与之前的棋子斜线相交
if( passive[queen[cur] + cur] == true || negative[n_sub + cur - queen[cur]] == true) {
flag = false ;
// cout<<"出现斜线相交,该位置不合法"<<endl ;
}
else
flag = true ;
if(flag) { //没有斜交,位置合法
// cout<<"斜线也没有相交,该位置合法"<<endl ;
if(cur == n-1) //如果是最后一个棋子
{
// cout<<"棋子走完一轮,总走法加1"<<endl ;
count++ ; //总走法加一 ;
}
row[queen[cur]] = true ;// 当前行设为有棋子
passive[queen[cur] + cur] = true ;//当前行正斜率方向有棋子
negative[n_sub + cur - queen[cur]] = true ; //当前行负斜率方向上也有棋子
cur++ ;
if(cur >= n) {
cur-- ;
row[queen[cur]] = false ;
passive[queen[cur] + cur] = false ;
negative[n_sub + cur - queen[cur]] = false ;//原理同回溯
}
flag = false ;
}
}
}//else
}
}
cout<<n<<"皇后问题一共有"<<count<<"种解法"<<endl ;
return 0 ;
}
你自己修改一下吧。
⑼ C语言编制黑白棋游戏:
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>
short int chess[12][12];
short int next[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};/*方向数组*/
void print(); /*输出函数*/
void calculate(); /*数子函数*/
int main()
{
int state; /*状态变量*/
/*介绍*/
printf(" 黑白棋 ");
printf("1.黑方先行,双方交替下棋。 2.一步合法的棋步包括:在一个空格新落下一个棋子,并且翻转对手一个或多个棋子。 3.新落下的棋子与棋盘上已有的同色棋子间,对方被夹住的所有棋子都要翻转过来。可以是横着夹,竖着夹,或是斜着夹。夹住的位置上必须全部是对手的棋子,不能有空格。 4.一步棋可以在数个方向上翻棋
,任何被夹住的棋子都必须被翻转过来,棋手无权选择不去翻某个棋子。
5.除非至少翻转了对手的一个棋子,否则就不能落子。如果一方没有合法棋步,也就是说不管他下到哪里,都不能至少翻转对手的一个棋子,那他这一轮只能弃权,而由他的对手继续落子直到他有合法棋步可下。
6.如果一方至少有一步合法棋步可下,他就必须落子,不得弃权。
7.棋局持续下去,直到棋盘填满或者双方都无合法棋步可下。
8.输入坐标时,分别输入横纵坐标,如: 7 2 表示第7行,第2列。
9.在游戏时,若想查看规则,请输入 0 0 。
10.形势判断请输入 9 9 。
");
printf(" 1=开始 0=退出 ");
scanf("%d",&state);
if(state==0)
return 0;
else if(state==1)
system("cls");
else
{
printf("错误!");
return 0;
}
/*初始化*/
memset(chess,0,sizeof(chess));
chess[5][5]=1,chess[4][4]=1,chess[5][4]=2,chess[4][5]=2;
/*开始*/
int i,j,k; /*i用于步数循环*/
int x,y; /*横纵坐标*/
int nx,ny; /*檎蚁乱桓鲎?/
int white,black;
for(i=5;i<=64;i++)
{
/*黑方的步骤 */
print();
place:
printf("黑方请输入坐标:");
scanf("%d%d",&x,&y);
if(x==0&&y==0) /*查看规则*/
{
system("cls");
printf("1.黑方先行,双方交替下棋。 2.一步合法的棋步包括:在一个空格新落下一个棋子,并且翻转对手一个或多个棋子。 3.新落下的棋子与棋盘上已有的同色棋子间,对方被夹住的所有棋子都要翻转过来。可以是横着夹,竖着夹,或是斜着夹。夹住的位置上必须全部是对手的棋子,不能有空格。 4.一步棋可以在数个方向上翻棋,任何被夹住的棋子都必须被翻转过来,棋手无权选择不去翻某个棋子。 5.除非至少翻转了对手的一个棋子,否则就不能落子。如果一方没有合法棋步,也就是说不管他下到哪里,都不能至少翻转对手的一个棋子,那他这一轮只能弃权,而由他的对手继续落子直到他有合法棋步可下。 6.如果一方至少有一步合法棋步可下,他就必须落子,不得弃权。 7.棋局持续下去,直到棋盘填满或者双方都无合法棋步可下。 8.输入坐标时,分别输入横纵坐标,如: 7 2 表示第7行,第2列。 9.在游戏时,若想查看规则,请输入 0 0 。 10.形势判断请输入 9 9 。 ");
guize:
printf(" 输入1以继续 ");
scanf("%d",&state);
if(state==1)
{
system("cls");
goto place;
}
else
{
printf("错误 ");
goto guize;
}
}
else if(x==9&&y==9)
{
calculate();
goto place;
}
/*判断落子是否合法*/
if(chess[x][y]!=0)
{
printf("非法的落子:该点已有棋! ");
goto place;
}
else
{
bool whether=false; /*是否合法:true表示合法*/
for(j=0;j<=7;j++)
{
nx=x;
ny=y;
white=0;
while(1)
{
nx=nx+next[j][0];
ny=ny+next[j][1];
if((chess[nx][ny]==0&&white==0)||(nx>8||nx<1||ny>8||ny<1))
{
break;
}
else if(chess[nx][ny]==2)
{
white++;
}
else if(chess[nx][ny]==1&&white>0)
{
int change=0;
chess[x][y]=1;
whether=true;
nx=x;
ny=y;
while(change<=white)
{
nx=nx+next[j][0];
ny=ny+next[j][1];
chess[nx][ny]=1;
change++;
}
break;
}
}
if(j==7&&whether==false)
{
printf("非法的落子:该子不能翻转对方棋子! ");
goto place;
}
}
}
system("cls");
print();
Sleep(3000);
/*白方的步骤*/
bool w=false; /*白方是否无棋可走*/
int recordj,recordk; /*记录*/
for(j=1;j<=8;j++)
{
for(k=1;k<=8;k++)
{
bool whether=false; /*是否合法:true表示合法*/
int num=0,sum=0; /*计数*/
for(int l=0;l<=7;l++)
{
black=0;
nx=j;
ny=k;
while(1)
{
nx=nx+next[l][0];
ny=ny+next[l][1];
if((chess[nx][ny]==0)||(nx>8||nx<1||ny>8||ny<1))
{
break;
}
else if(chess[nx][ny]==1)
{
black++;
}
else if(chess[nx][ny]==2&&black>0)
{
whether=true;
w=true;
break;
}
}
if(whether==true)
{
sum+=black;
}
}
if(sum>num)
{
num=sum;
recordj=j;
recordk=k;
}
}
}
if(w==true)
{
chess[recordj][recordk]=2;
for(int m=0;m<=7;m++)
{
nx=recordj;
ny=recordk;
black=0;
while(1)
{
nx=nx+next[m][0];
ny=ny+next[m][1];
if((chess[nx][ny]==0)||(nx>8||nx<1||ny>8||ny<1))
{
break;
}
else if(chess[nx][ny]==1)
{
black++;
}
else if(chess[nx][ny]==2&&black>0)
{
int change=0;
nx=recordj;
ny=recordk;
while(change<=black)
{
nx=nx+next[m][0];
ny=ny+next[m][1];
chess[nx][ny]=2;
change++;
}
break;
}
}
}
}
else/*白方无棋可走*/
{
printf("白方无棋可走 ");
}
Sleep(1000);
system("cls");
}
return 0;
}
void print()
{
int p,q;
printf(" 1 2 3 4 5 6 7 8 ");
for(p=1;p<=8;p++)
{
printf("%d",p);
for(q=1;q<=8;q++)
{
if(chess[p][q]==1)
printf("●");
else if(chess[p][q]==2)
printf("○");
else
printf(" ");
}
printf(" ");
}
}
void calculate()
{
int pp,qq;
int bla=0,whi=0;
for(pp=1;pp<=8;pp++)
{
for(qq=1;qq<=8;qq++)
{
if(chess[pp][qq]==1)
bla++;
else if(chess[pp][qq]==2)
whi++;
}
}
printf("黑子数:%d 白子数:%d ",bla,whi);
}
⑽ 在C语言中,什么叫做“面向对象”,什么叫做“面向过程”
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了。
而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。
可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。
功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。