史上最详细的手把手三子棋小游戏全教程来啦!!!!
不过在着手制作之前,我们首先要把逻辑理清楚, 三子棋首先得有个棋盘对吧,在C语言里面,我们就用一个二维数组来表示棋盘
1.首先对棋盘进行初始化
void init(void){ //初始化棋盘
int i, j;
for (i = 0; i <= 2; ++i)
for (j = 0; j <= 2; ++j){
g_chess[i][j] = ' ';
}
}
2.初始化完了之后,我们就需要一个函数来把棋盘 打印在屏幕上
void printfchess(void){//打印棋盘
int i;
for (i = 0; i < 3; ++i){
printf(" | %c | %c | %c | \n", g_chess[i][0], g_chess[i][1], g_chess[i][2]);
if (i<2)
printf(" -------------\n");
}
}
3.除了打印和初始化,我们还需要一个判定输赢,还有棋子是否已经满了的函数
判断输赢
int checkwinner(){
int row, list;
for (row = 0; row <= 2; ++row){
for (list = 0; list <= 2; ++list){
if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'O')
return 2;//返回2是电脑赢
if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'O')
return 2;
if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'X')
return 1;//返回1是人赢
if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'X')
return 1;
}
if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'X')
return 1;
if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'X')
return 1;
if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'O')
return 2;
if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'O')
return 2;
}
}
棋子满
int checkfull(){//检查是否已满
int i;
int j;
for (i = 0; i <= 2; i++){
for (j = 0; j <= 2; j++){
if (g_chess[i][j] == ' ')
return 4;
}
}
return 3;
}
4.之后就是我们的重头戏了,一个playgame函数将上面的函数 涵盖进来并进行每一次的下棋
int playgame(){
int row = 0, list = 0;
int gameget = 0;
int gamegot = 0;
srand((int)time(0));
while (1){
gameget = rand() % 3;//不能直接让随机值作为下标不然调用的时候每次都获得一个新的值,
//从而覆盖上一个应该用一个临时变量保存随机数的值
gamegot = rand() % 3;
if (g_chess[gameget][gamegot] != 'X' && g_chess[gameget][gamegot] != 'O'){
g_chess[gameget][gamegot] = 'O';
printf("\n请电脑下棋\n");
printfchess();//打印棋盘
break;
}
}
if (checkwinner() == 2){ //一定要在下棋后检查,因为三子棋,是九个格子!!!
printf("电脑获胜\n");
return 0;
}
if (checkfull() == 3){
printf("和棋\n");
return 0;
}
while (1){
printf("请玩家下棋,先行后列输入坐标\n");//玩家下棋
scanf("%d %d", &row, &list);
if (g_chess[row][list] == 'X' || g_chess[row][list] == 'O'){ //该if与下面的else if循序不能颠倒,否则会有逻辑错误
printf("该地方已有棋子,请重新输入\n");
continue;//如果输入不对则重来,直到进入下一条件判断
}
else if (row <= 2 && row >= 0 && list <= 2 && list >= 0){
g_chess[row][list] = 'X';
printf("\n");
printfchess();//打印棋盘
break;//易错点,不能用continue跳出循环,否则会导致while无限循环
}
else{
printf("坐标不在棋盘内,请重新输入\n");
continue;
}
}
if (checkwinner() == 1){
printf("玩家获胜\n");
return 0;
}
if (checkfull() == 3){
printf("和棋\n");
return 0;
}
}
5.最后将上面这一个个模块整合起来就是完整的三子棋代码了
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
char g_chess[3][3] = { 0 };
void init(void){ //初始化棋盘
int i, j;
for (i = 0; i <= 2; ++i)
for (j = 0; j <= 2; ++j){
g_chess[i][j] = ' ';
}
}
int checkwinner(){
int row, list;
for (row = 0; row <= 2; ++row){
for (list = 0; list <= 2; ++list){
if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'O')
return 2;//返回2是电脑赢
if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'O')
return 2;
if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'X')
return 1;//返回1是人赢
if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'X')
return 1;
}
if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'X')
return 1;
if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'X')
return 1;
if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'O')
return 2;
if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'O')
return 2;
}
}
int checkfull(){//检查是否已满
int i;
int j;
for (i = 0; i <= 2; i++){
for (j = 0; j <= 2; j++){
if (g_chess[i][j] == ' ')
return 4;
}
}
return 3;
}
void printfchess(void){//打印棋盘
int i;
for (i = 0; i < 3; ++i){
printf(" | %c | %c | %c | \n", g_chess[i][0], g_chess[i][1], g_chess[i][2]);
if (i<2)
printf(" -------------\n");
}
}
int playgame(){
int row = 0, list = 0;
int gameget = 0;
int gamegot = 0;
srand((int)time(0));
while (1){
gameget = rand() % 3;//不能直接让随机值作为下标不然调用的时候每次都获得一个新的值,
//从而覆盖上一个应该用一个临时变量保存随机数的值
gamegot = rand() % 3;
if (g_chess[gameget][gamegot] != 'X' && g_chess[gameget][gamegot] != 'O'){
g_chess[gameget][gamegot] = 'O';
printf("\n请电脑下棋\n");
printfchess();//打印棋盘
break;
}
}
if (checkwinner() == 2){ //一定要在下棋后检查,因为三子棋,是九个格子!!!
printf("电脑获胜\n");
return 0;
}
if (checkfull() == 3){
printf("和棋\n");
return 0;
}
while (1){
printf("请玩家下棋,先行后列输入坐标\n");//玩家下棋
scanf("%d %d", &row, &list);
if (g_chess[row][list] == 'X' || g_chess[row][list] == 'O'){ //该if与下面的else if循序不能颠倒,否则会有逻辑错误
printf("该地方已有棋子,请重新输入\n");
continue;//如果输入不对则重来,直到进入下一条件判断
}
else if (row <= 2 && row >= 0 && list <= 2 && list >= 0){
g_chess[row][list] = 'X';
printf("\n");
printfchess();//打印棋盘
break;//易错点,不能用continue跳出循环,否则会导致while无限循环
}
else{
printf("坐标不在棋盘内,请重新输入\n");
continue;
}
}
if (checkwinner() == 1){
printf("玩家获胜\n");
return 0;
}
if (checkfull() == 3){
printf("和棋\n");
return 0;
}
}
int main(void){
init();//初始化棋盘
printf("游戏开始\n");
while (1){
if (playgame() == 0)
break;
//如果不出现胜利者或者和棋,则回到循环继续游戏
}
return 0;
}
最后一些容易 出错的地方进行 整理一下
1.判断胜利的 函数要放在和棋之前,否则最后一个子下的时候会将胜利给掩盖掉
2.一定要在电脑和人下子之后分别进行一次检查,因为三子棋只有九个格,如果在电脑和人都 下了子之后才统一进行判断的话讲无法判断最后一个子的情况(简单的说就是一个九个格子的棋盘内每次下两个子,然后统一判断人赢还是电脑赢,当下到第八个子时已经没有足够的空间让人和电脑都下一个子了)
3.在循环中时 要注意区分continue和break和细微差别
4. 随机种子不能放进循环内,因为 计算机运行速度极快,随机种子是截取时间作为伪随机运算的参数,放进循环内会导致随机种子不能有效 得到随机数
还有一些 容易出错的地方我已经在代码的注释中说得很清楚了,希望对你 有所帮助( Φ ω Φ )