三子棋
- 五子棋是我从小玩到大的,以前未有手机,却能每天快快乐乐的和小伙伴玩一整天(想想也真是怀念啊),本来想写一个五子棋,但是能力不够 (等我再琢磨琢磨) 目前来说只能写出三子棋,在这里我想以自己尽力大的想法让大家更方便理解三子棋的精妙之处;
一、菜单介绍
-
相信大家在打单机游戏的时候,肯定会看到一个菜单(目录),也就是在刚刚进入游戏的时候看到的选项
-
1.play(进入游戏),选择模式(1.单人模式 2.双人模式0.返回)
-
0.exit(退出游戏)
void menu()
{
printf("*************************************\n");
printf("*************************************\n");
printf("*************************************\n");
printf("********** 1.play 0.exit **********\n");
printf("*************************************\n");
printf("*****************************************\n");
printf("*********************************************\n");
}
void play()
{
printf("*************************************\n");
printf("*************************************\n");
printf("*************************************\n");
printf("********** 1.computer 2.player **********\n");
printf("**************** 0.return *****************\n");
printf("*********************************************\n");
printf("**********************************************\n");
}
主程序完成
int main()
{
int i = 0;
int j = 0;
do
{
agin:
menu();
printf("请选择:");
scanf("%d", &i);
switch (i)
{
case 1:
do
{
play();
printf("请选择:");
scanf("%d", &j);
switch (j)
{
case 1:
game1();//单人
/*printf("单人");*/
printf("\n");
break;
case 2:
game2();//双人
/*printf("双人");*/
printf("\n");
break;
case 0:
goto agin;
default:
printf("输入错误,请重新选择\n");
break;
}
} while (j);
printf("\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (i);
return 0;
}
- 完成这些就可以开始写进行玩游戏的过程了:
二、棋盘设置
因为棋盘类似于一个二维数组,所以用一个二维数组来接收下的棋子的“字符”;
第一种:直接打印出这个棋盘
如:把‘*’看成要玩家输出的字符“%c”
* | * | *
---|---|---
* | * | *
---|---|---
* | * | *
所以可以将第一行看成:* | * | *
第二行: —|—|—
这样就可以打印出棋盘;
代码实现:
void Display(char board[BOW][COL], int bow, int col)
{
int i = 0;
for (i = 0; i < bow; i++)
{
printf(" %c | %c | %c ", board[i][0], board[i][1], board[i][2]);
printf("\n");
if(i<bow-1)
printf("---|---|---");
printf("\n");
}
}
第一种有一个缺陷,就是定死了行和列,对于后期如果想改麻烦。
第二种:优化版
- 在第一种的基础上进行优化,进行优化其缺陷:
- 主要想法在把“ %c ”“|”分开打印, 把“—”“|”也分开打印。
- 因为在棋盘的最后一行没有“—”,和最后一列没有“|”
- 如:
void Display(char board[BOW][COL], int bow, int col)
{
int i = 0;
for (i = 0; i < bow; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if(j<col-1)
printf("|");
}
printf("\n");
if (i < bow - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
经过这么久终于是到了最关键的下棋了:
三、computer模式
- 也就是常说的人机试炼,旁边没人和你玩,不就只能和电脑玩玩喽,不要感到孤单,因为我也是这样(哭死…),好了不说了,要说人机模式下棋呗。
- 那就是玩家(也就是你自己)下一步,然后电脑在下一步,直到谁赢,输,平局,所以无论在你下完一步后还是在电脑下完一步后,都要判断这局游戏的输赢,但是判断三字棋局的输赢,除了三字连成线,也就是横三条,竖三条,斜两条,可表示输赢,还有如果棋子下完了棋盘还没有分出胜负,那就是平局,其他情况就继续下棋。
先用函数 Playgame1();表示玩家下一步棋子,用字符‘’表示
再是Computer(); 表示电脑下一步棋,用字符‘#’表示
再完成一个函数 Judge();判断棋局输赢,需要一个返回值,如果玩家赢返回‘’;如果输返回‘#’,平局返回‘P’,继续则返回‘C’;
代码实现:
while (1)
{
//下棋
//玩家下棋
Playgame1(board, BOW, COL);
Display(board, BOW, COL);//打印出棋盘
ret = Judge(board, BOW, COL);
if (ret != 'C')
break;
//电脑下棋
Computer(board, BOW, COL);
Display(board, BOW, COL);//打印出棋盘
ret=Judge(board, BOW, COL);//判断输赢
if (ret != 'C')
break;
}
if (ret == '#')
printf("玩家输\n");
if (ret == '*')
printf("玩家赢\n");
if (ret == 'P')
printf("平局\n");
- 大概流程了解后,则完成函数 Playgame1();实现
因为数组的下标是从0开始,但是,不是所有的玩家都懂这点,所以输入的值要从1开始但不大于这一行(列),还有些特殊情况已经下过的坐标不能再下子了。
代码实现:
void Playgame1(char board[BOW][COL], int bow, int col)
{
int i = 0;
int j = 0;
while (1)
{
printf("玩家1请输入一个坐标:");
scanf("%d%d", &i, &j);
if (i >= 1 && i <= bow && j <= col && j >= 1)
{
if (board[i-1][j-1] == ' ')
{
board[i-1][j-1] = '*';
break;
}
else
printf("已占格,请重新输入:\n");
}
else
printf("输入坐标错误,请重新输入:\n");
}
}
- 再完成函数computer();电脑下棋
电脑的话就是生成随机值,再下到棋盘中呗,但也是界的,在这个界限里可以随机下子,但不能下在已经下过的位置上。
代码实现:
void Computer(char board[BOW][COL], int bow, int col)
{
printf("电脑下棋:\n");
while (1)
{
int i = rand() % bow;
int j = rand() % col;
if (board[i][j] == ' ')
{
board[i][j] = '#';
break;
}
}
}
在使用了rand()函数,要使用srand()函数,在这里只需要调用一次这个srand()函数,在项目开始的地方只用一次就可以。
srand((unsigned int)time(NULL));
- 最后的是判断输赢的函数实现:
int Into(char board[BOW][COL], int bow, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < bow; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char Judge(char board[BOW][COL], int bow, int col)
{
int i = 0;
//三行相等的情况
for (i = 0; i < bow; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2]&&board[i][1]!=' ')
{
return board[i][0];
}
}
//三竖相等的情况
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[0][i];
}
}
//最后两条斜条相等的情况
if (board[0][0] == board[1][1] && board[2][2] == board[1][1] && board[1][1] != ' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//到最后棋盘中如果填满了,就平局了
//创造一个函数判断棋盘中还有没有‘ ’
if (Into(board, BOW, COL) == 1)//再分装出一个函数判断棋盘中还有没有‘ ’;
{
return 'P';
}
//最后如果都不满足则:继续,
return 'C';
}
这里的进行判断还是有一种优化版,因为在这个代码中也定死了,我的优化想法:判断输赢的话:行的情况就判断连在一起的数组位置进行判断,就是数组第一个和其后面两个进行比较是否相等,竖的情况就判断其下面两个进行比较,还有与其斜方向进行比较就可以了。
最后的实现:
void game1()//单人模式
{
char board[BOW][COL] = { 0 };
Inboard(board, BOW, COL);//初始化
Display(board, BOW, COL);//打印棋盘
char ret = 0;
while (1)
{
//下棋
//玩家下棋
Playgame1(board, BOW, COL);
Display(board, BOW, COL);
ret = Judge(board, BOW, COL);
if (ret != 'C')
break;
//电脑下棋
Computer(board, BOW, COL);
Display(board, BOW, COL);
ret=Judge(board, BOW, COL);//判断输赢
if (ret != 'C')
break;
}
if (ret == '#')
printf("玩家输\n");
if (ret == '*')
printf("玩家赢\n");
if (ret == 'P')
printf("平局\n");
}
四、玩家对战
在这里我想补充一个玩家对战模式,游戏怎么可以没有玩家对战呢?(当然还不能远程操控),在同一个键盘上使用还是可以的。
- 玩家对战就是把原来电脑下的棋这一个函数,该成另一个玩家2下的棋,这个函数只需要在原有的 Playgame1();进行一点改变为Playgame2();
具体实现:
void Playgame2(char board[BOW][COL], int bow, int col)
{
int i = 0;
int j = 0;
while (1)
{
printf("玩家2请输入一个坐标:");
scanf("%d%d", &i, &j);
if (i >= 1 && i <= bow && j <= col && j >= 1)
{
if (board[i - 1][j - 1] == ' ')
{
board[i - 1][j - 1] = '#';
break;
}
else
printf("已占格,请重新输入:\n");
}
else
printf("输入坐标错误,请重新输入:\n");
}
}
void game2()//双人模式
{
char board[BOW][COL] = { 0 };
Inboard(board, BOW, COL);//初始化
Display(board, BOW, COL);//打印棋盘
char ret = 0;
while (1)
{
Playgame1(board, BOW, COL);
Display(board, BOW, COL);
ret = Judge(board, BOW, COL);//判断输赢
if (ret != 'C')
break;
Playgame2(board, BOW, COL);
Display(board, BOW, COL);
ret = Judge(board, BOW, COL);//判断输赢
if (ret != 'C')
break;
}
if (ret == '#')
printf("玩家输\n");
if (ret == '*')
printf("玩家赢\n");
if (ret == 'P')
printf("平局\n");
}
程序的目录如下:
int main()
{
srand((unsigned int)time(NULL));
int i = 0;
int j = 0;
do
{
agin:
menu();
printf("请选择:");
scanf("%d", &i);
switch (i)
{
case 1:
do
{
play();
printf("请选择:");
scanf("%d", &j);
switch (j)
{
case 1:
game1();//单人
/*printf("单人");*/
printf("\n");
break;
case 2:
game2();//双人
/*printf("双人");*/
printf("\n");
break;
case 0:
goto agin;
default:
printf("输入错误,请重新选择\n");
break;
}
} while (j);
printf("\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (i);
return 0;
}
最后三子棋祝愿大家都可以写出完美的代码;