目录
前言
一,游戏规则
二,游戏步骤
三,游戏实现
3.1游戏构思和框架
3.2 棋盘的初始化和打印
3.3 玩家和电脑下棋的实现
3.4 判断输赢
3.5 游戏平局
3.6 游戏头文件game.h
四,电脑下棋优化
五,游戏总代码
前言
继上一次的猜数字小游戏以后,我们再来个更加锻炼一个逻辑的游戏,这个游戏比上个代码多,但很能考验我们的逻辑能力。逻辑能力上来了,以后做项目,编写程序的时候就不会太吃力。话不多说,先来一张美图,直接开始。
一,游戏规则
跟小时候在作业本上画个“井”子格一样,谁先连成一条线谁赢。如果棋盘满了还没有分出胜负,则平局。只不过这次在电脑上和人机下棋,在电脑上显示“井”子格。这次玩家棋子用“ # ”表示,电脑用“ * ”表示。
二,游戏步骤
游戏的步骤如下:
第一步,玩家下棋
第二步,电脑下棋
第三步,如果没分出胜负重复1,2步骤,一旦有一方胜利就终止游戏。
另外还要注意的是:
1,在游戏步骤执行之前,我们想一下,在开始之前应该有一个菜单,来满足我们是否要选择玩游戏。而游戏结束之后应该跳到菜单界面,由玩家选择是否还要玩游戏。
2,在执行游戏步骤的时候,玩家和电脑下棋之后到要进行判断输赢。
3,三子棋总共有九格,那三子棋的实现就应该是用3*3二维数组来实现,每一个格子放一个数。更何况我们不能直接在屏幕上来下,我们可以用坐标来代替,而二维数组正好可以满足要求。
三,游戏实现
3.1游戏构思和框架
这次我们把这个游戏分别放在不同的文件中,游戏框架放在test.c源文件中,游戏实现放在game.c源文件中,函数声明放在game.h头文件中。
我们现在头文件里添加个库函数<stdio.h>,然后把3分别赋值给ROW,LOW这样做是为了以后要是写四子棋,五子棋时只用修改ROW和LOW赋的值就行了。
//game.h
#include<stdio.h>
#defile ROW 3
#defile COL 3
然后我们将头文件test.h作为test.c的库函数(这样就相当于直接调用test.h里的内容了)和游戏框架如下所示:
//test.c
#include"game.h"void mune()
{printf("******************************\n");printf("******** 1.开始游戏 **********\n");printf("******** 0.退出游戏 **********\n");printf("******************************\n");
}int main()
{int input = 0;srand((unsigned)time(NULL)); //随机数的起点,后面会提到do{mune();//打印游戏菜单printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 0:break;default:printf("选择错误,重新选择。\n");break;}} while (input);return 0;}
用do...while()语句来实现整个框架,先把菜单打印出来,然后看着菜单进行选择,将选项赋值在变量input中,然后再用switch语句来执行不同的选项,将游戏实现的过程放在game() 函数中。
然后接下来我们开始编写game() 函数。
根据构思我们可以想出以下步骤:
1,屏幕出现棋盘。
2,玩家输入坐标下棋,判断输赢,没赢继续执行下一步。
3,电脑下棋,判断输赢,没赢执行第1步。
3.2 棋盘的初始化和打印
既然出现棋盘,那我们就先创建一个3*3棋盘,并对棋盘进行初始化(让棋盘里的内容都变成空格)。然后打印棋盘:
//test.c
void game()
{char chessboard[ROW][COL];//创建一个3*3的棋盘init_chessboard(chessboard, ROW, COL);//初始化棋盘print_chessboard(chessboard, ROW, COL);//打印棋盘
}
我们将棋盘的初始化和打印棋盘的实现放在game.c文件中,game.c中也一样将game.h作为库函数调用。
//game.c
#include "game.h"
void init_chessboard(char chessboard[ROW][COL],int row,int col)//初始化棋盘
{int i,j;for(i = 0;i < row; i++){for(j = 0; j < col; j++){chessboard[i][j] = ' '; //先将棋盘中的数打印成空格}}}
void print_chessboard(char chessboard[ROW][COL],int row,int col)//打印棋盘
{int i,j;for(i = 0; i < row; i++) //运行三次后,打印棋盘{for(j = 0; j < col; j++) //运行三次后: %c | %c | %c {if(j == col - 1)printf(" %c ", chessboard[i][j]);elseprintf(" %c |", chessboard[i][j]);}printf("\n");for(j = 0; j < col; j++) //运行三次后: ---|---|---{if(i < 2){if(j == col - 1)printf("---");elseprintf("---|");}}printf("\n");}
}
3.3 玩家和电脑下棋的实现
当屏幕上打印棋盘后,玩家该输入坐标下棋。玩家下棋用‘#’表示,电脑下棋用‘*’表示
//test.c
void game()
{char chessboard[3][3]; //创建一个3*3的棋盘init_chessboard(chessboard, ROW, COL); //初始化棋盘print_chessboard(chessboard, ROW, COL); //打印棋盘player_playchess(chessboard, ROW, COL); //玩家下棋judge(chessboard, ROW, COL); //判断输赢computer_playchess(chessboard, ROW, COL); //电脑下棋}
在game.c中实现玩家和电脑下棋的操作。其中玩家下棋是输入坐标下棋,电脑是靠rand()来生成随机数来下棋。然后在test.c中加一个随机起点(srand((unsigned)time(NULL)))(具体rand()生成随机数可以看这篇的生成随机值)
如下:
//game.c
void player_playchess(char chessboard[ROW][COL],int row,int col)
{int input = 1;while(input){printf("请输入下棋的坐标\n");int a = 0; //创建a,b两个变量来储存坐标int b = 0;scanf("%d %d",&a,&b);if(a > 0 && a < row + 1 && b > 0 && b < col + 1) //坐标必须在0到row(col)+1之间{if(chessboard[a - 1][b - 1] == ' ') //判断输入坐标的地方是否为空格{chessboard[a - 1][b - 1] = '#';input = 0;}else printf("该坐标已被占用,请从新输入");}else{printf("坐标非法,请重新输入");}}print_chessboard(chessboard,row,col); //打印下棋后的棋盘}
//电脑下棋
void computer_playchess(int chessboard[ROW][COL], int row, int col)
{int input = 1;while(input){ int a = rand() % row; //用a,b装 0到2 的随机数int b = rand() % col;if(chessboard[a - 1][b - 1] == ' ') //判断输入坐标的地方是否为空格{chessboard[a - 1][b - 1] = '*';input = 0;}} print_chessboard(chessboard,row,col); //打印下棋后的棋盘
}
3.4 判断输赢
在电脑和玩家下棋后要判断输赢,如果平局,返回‘Q’,如果都没有赢,就返回 'P',游戏继续。
//game.cchar judge(int chessboard[ROW][COL],int row,int col)
{int i = 0;for(i = 0; i < row; i++){if(chessboard[i][0] == chessboard[i][1] && chessboard[i][1] == chessboard[i][2] && chessboard[i][0] != ' '){return chessboard[i][0]; //判断一行是否相同}if(chessboard[0][i] == chessboard[1][i] && chessboard[1][i] == chessboard[2][i] && chessboard[0][i] != ' '){return chessboard[0][i]; //判断一列是否相同}}if(chessboard[0][0] == chessboard[1][1] && chessboard[1][1] == chessboard[2][2] && chessboard[0][0] != ' '){return chessboard[0][0]; //判断右斜线是否相同} if(chessboard[0][2] == chessboard[1][1] && chessboard[1][1] == chessboard[2][0] && chessboard[1][1] != ' '){return chessboard[0][2]; //判断左斜线是否相同}if(if_full(chessboard,row,col)) //判断是否平局,平局返回‘Q’{return 'Q';} return 'P';}
与电脑下棋一来一回后,棋盘还未满,加一个while循环。如下
//test.c
void game()
{int char = 0; //装判断函数的返回值char chessboard[3][3]; //创建一个3*3的棋盘init_chessboard(chessboard, ROW, COL); //初始化棋盘print_chessboard(chessboard, ROW, COL); //打印棋盘while(1) {player_playchess(chessboard, ROW, COL); //玩家下棋ret = judge(chessboard, ROW, COL); //判断输赢if( ret != 'P') //judge函数返回'P',游戏继续{break;} computer_playchess(chessboard, ROW, COL); //电脑下棋ret = judge(chessboard, ROW, COL); //判断输赢if( ret != 'P'){break;}
}
3.5 游戏平局
如果三子棋棋盘都满了,并且还没分出胜负,游戏就平局。if_full判断棋盘是否满了,如全满返回1,然后在前面judge函数中返回'Q',来表示平局。
//game.c
int if_full(int chessboard[ROW][COL],int row,int col)
{int i = 0;for(i = 0; i < row; i++){int j = 0;for(j = 0; j < col; j++){if(chessboard[i][j] == ' ')return 0; //遍历一遍是否有空格,有返回0}}return '1'; //如果棋盘都没有空格,返回‘1’
}
接着如果将judge返回值放在ret中,如果ret == '#',玩家胜利。如果ret == ' * ',电脑胜利。如果ret == 'Q',游戏平局。代码如下:
//test.c
void game()
{char ret = 0; //装判断输赢函数的返回值char chessboard[3][3]; //创建一个3*3的棋盘init_chessboard(chessboard, ROW, COL); //初始化棋盘print_chessboard(chessboard, ROW, COL); //打印棋盘while(1) {player_playchess(chessboard, ROW, COL); //玩家下棋ret = judge(chessboard, ROW, COL); //判断输赢if( ret != 'P') //judge函数返回'P',游戏继续{break;} computer_playchess(chessboard, ROW, COL); //电脑下棋ret = judge(chessboard, ROW, COL); //判断输赢if( ret != 'P'){break;} } if(ret == '#'){printf("玩家胜利!");}if(ret == '*'){printf("电脑胜利!");}if(ret == 'Q'){printf("游戏平局");}print_chessboard(chessboard, ROW, COL); //游戏结束再打印一下打印棋盘
}
3.6 游戏头文件game.h
将game.c源文件中代码的实现通过game.h头文件与test.c源文件进行联系。
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void init_chessboard(chessboard[ROW][COL], int ROW, int COL);
void print_chessboard(chessboard[ROW][COL], int ROW, int COL);
void player_playchess(chessboard[ROW][COL], int ROW, int COL);
void computer_playchess(chessboard[ROW][COL], int ROW, int COL);
void judge(chessboard[ROW][COL], int ROW, int COL);
四,电脑下棋优化
前面的电脑下棋太菜了,这次我们用代码提高电脑下棋水平。从而让“人工智障”变为“人工智能”。
我们需要电脑来“拦截”我们的棋子,当我们有两个棋子相连的时候三子棋,就要进行拦截了。否则,电脑随机下棋。实现代码如下:
int intell_computer(char chessboard[ROW][COL], int row, int col)
{int i = 0;//行判断for (i = 0; i < row; i++){if (chessboard[i][0] == chessboard[i][1] && chessboard[i][2] == ' '){chessboard[i][2] = '*';return 1;}if (chessboard[i][0] == chessboard[i][2] && chessboard[i][1] == ' '){chessboard[i][1] = '*';return 1;}if (chessboard[i][1] == chessboard[i][2] && chessboard[i][0] == ' '){chessboard[i][0] = '*';return 1;}}//列判断for (i = 0; i < col; i++){if (chessboard[0][i] == chessboard[1][i] && chessboard[2][i] == ' '){chessboard[2][i] = '*';return 1;}if (chessboard[0][i] == chessboard[2][i] && chessboard[1][i] == ' '){chessboard[1][i] = '*';return 1;}if (chessboard[1][i] == chessboard[2][i] && chessboard[0][i] == ' '){chessboard[0][i] = '*';return 1;}}//对角线判断if (chessboard[1][1] == chessboard[0][0] && chessboard[2][2] == ' '){chessboard[2][2] = '*';return 1;}if (chessboard[0][0] == chessboard[2][2] && chessboard[1][1] == ' '){chessboard[1][1] = '*';return 1;}if (chessboard[1][1] == chessboard[2][2] && chessboard[0][0] == ' '){chessboard[0][0] = '*';return 1;}//斜对角线判断if (chessboard[1][2] == chessboard[2][1] && chessboard[3][0] == ' '){chessboard[3][i] = '*';return 1;}if (chessboard[1][2] == chessboard[3][0] && chessboard[2][1] == ' '){chessboard[2][1] = '*';return 1;}if (chessboard[2][1] == chessboard[3][0] && chessboard[1][2] == ' '){chessboard[1][2] = '*';return 1;}return 0;
}
我们把这代码插入computer_playchess的实现里,代码如下:
//电脑下棋void computer_playchess(char chessboard[ROW][COL], int row, int col){printf("电脑下棋\n");if (intell_computer(chessboard, row, col)) //判断是否复合拦截条件,复合进行拦截。{;}else{while (1){int a = rand() % row; //用a,b装 0到2 的随机数int b = rand() % col;if (chessboard[a][b] == ' ') //判断输入坐标的地方是否为空格{chessboard[a][b] = '*';break;}}}print_chessboard(chessboard,row,col); //打印下棋后的棋盘 }
五,游戏总代码
//game.h
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void init_chessboard(chessboard[ROW][COL], int ROW, int COL);
void print_chessboard(chessboard[ROW][COL], int ROW, int COL);
void player_playchess(chessboard[ROW][COL], int ROW, int COL);
void computer_playchess(chessboard[ROW][COL], int ROW, int COL);
void judge(chessboard[ROW][COL], int ROW, int COL);
//test.c
//test.c
#include"game.h"void mune()
{printf("******************************\n");printf("******** 1.开始游戏 **********\n");printf("******** 0.退出游戏 **********\n");printf("******************************\n");
}
void game()
{char ret = 0;char chessboard[3][3] = { 0 }; //创建一个3*3的棋盘init_chessboard(chessboard, ROW, COL); //初始化棋盘system("cls");print_chessboard(chessboard, ROW, COL); //打印棋盘while (1){player_playchess(chessboard, ROW, COL); //玩家下棋print_chessboard(chessboard, ROW, COL); //打印下棋后的棋盘ret = judge(chessboard, ROW, COL); //判断输赢if (ret != 'P') //judge函数返回'P',游戏继续{break;}computer_playchess(chessboard, ROW, COL); //电脑下棋ret = judge(chessboard, ROW, COL); //判断输赢if (ret != 'P'){break;}}if (ret == '#'){printf("玩家胜利!\n");}if (ret == '*'){printf("电脑胜利!\n");}if (ret == 'Q'){printf("游戏平局\n");}print_chessboard(chessboard, ROW, COL); //游戏结束再打印一下打印棋盘
}int main()
{int input = 0;srand((unsigned)time(NULL)); //随机数的起点,后面会提到do{mune();//打印游戏菜单printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 0:break;default:printf("选择错误,重新选择。\n");break;}} while (input);return 0;}
//game.c
#include "game.h"
int intell_computer(char chessboard[ROW][COL], int row, int col)
{int i = 0;//行for (i = 0; i < row; i++){if (chessboard[i][0] == chessboard[i][1] && chessboard[i][2] == ' '){chessboard[i][2] = '*';return 1;}if (chessboard[i][0] == chessboard[i][2] && chessboard[i][1] == ' '){chessboard[i][1] = '*';return 1;}if (chessboard[i][1] == chessboard[i][2] && chessboard[i][0] == ' '){chessboard[i][0] = '*';return 1;}}//列for (i = 0; i < col; i++){if (chessboard[0][i] == chessboard[1][i] && chessboard[2][i] == ' '){chessboard[2][i] = '*';return 1;}if (chessboard[0][i] == chessboard[2][i] && chessboard[1][i] == ' '){chessboard[1][i] = '*';return 1;}if (chessboard[1][i] == chessboard[2][i] && chessboard[0][i] == ' '){chessboard[0][i] = '*';return 1;}}//对角线if (chessboard[1][1] == chessboard[0][0] && chessboard[2][2] == ' '){chessboard[2][2] = '*';return 1;}if (chessboard[0][0] == chessboard[2][2] && chessboard[1][1] == ' '){chessboard[1][1] = '*';return 1;}if (chessboard[1][1] == chessboard[2][2] && chessboard[0][0] == ' '){chessboard[0][0] = '*';return 1;}//斜对角线if (chessboard[1][2] == chessboard[2][1] && chessboard[3][0] == ' '){chessboard[3][i] = '*';return 1;}if (chessboard[1][2] == chessboard[3][0] && chessboard[2][1] == ' '){chessboard[2][1] = '*';return 1;}if (chessboard[2][1] == chessboard[3][0] && chessboard[1][2] == ' '){chessboard[1][2] = '*';return 1;}return 0;
}
void init_chessboard(char chessboard[ROW][COL],int row,int col)//初始化棋盘
{int i, j;for (i = 0; i < row; i++){for (j = 0; j < col; j++){chessboard[i][j] = ' '; //先将棋盘中的数打印成空格}}}
void print_chessboard(char chessboard[ROW][COL], int row, int col)//打印棋盘
{int i, j;for (i = 0; i < row; i++) //运行三次后,打印棋盘{for (j = 0; j < col; j++) //运行三次后: %c | %c | %c {if (j == col - 1)printf(" %c ", chessboard[i][j]);elseprintf(" %c |", chessboard[i][j]);}printf("\n");for (j = 0; j < col; j++) //运行三次后: ---|---|---{if (i < row - 1){if (j == col - 1)printf("---");elseprintf("---|");}}printf("\n");}
}//game.cvoid player_playchess(char chessboard[ROW][COL], int row, int col){printf("玩家下棋\n");int a = 0; //创建a,b两个变量来储存坐标int b = 0;while (1){printf("请输入下棋的坐标\n");scanf("%d %d", &a, &b);if (a > 0 && a < row + 1 && b > 0 && b < col + 1) //坐标必须在0到row(col)+1之间{if (chessboard[a - 1][b - 1] == ' ') //判断输入坐标的地方是否为空格{chessboard[a - 1][b - 1] = '#';break;}elseprintf("该坐标已被占用,请重新输入坐标\n");}else{printf("坐标非法,请重新输入\n");}}}//电脑下棋void computer_playchess(char chessboard[ROW][COL], int row, int col){printf("电脑下棋\n");if (intell_computer(chessboard, row, col)){;}else{while (1){int a = rand() % row; //用a,b装 0到2 的随机数int b = rand() % col;if (chessboard[a][b] == ' ') //判断输入坐标的地方是否为空格{chessboard[a][b] = '*';break;}}}print_chessboard(chessboard,row,col); //打印下棋后的棋盘 }static int if_full(char chessboard[ROW][COL], int row, int col){int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if (chessboard[i][j] == ' ')return 0; //遍历一遍是否有空格,有返回0}}return 1; //如果棋盘都没有空格,返回‘1’}char judge(char chessboard[ROW][COL], int row, int col){int i = 0;for (i = 0; i < row; i++){if (chessboard[i][0] == chessboard[i][1] && chessboard[i][1] == chessboard[i][2] && chessboard[i][0] != ' '){return chessboard[i][0]; //判断一行是否相同}}for (i = 0; i < row; i++){if (chessboard[0][i] == chessboard[1][i] && chessboard[1][i] == chessboard[2][i] && chessboard[0][i] != ' '){return chessboard[0][i]; //判断一列是否相同}}if (chessboard[0][0] == chessboard[1][1] && chessboard[1][1] == chessboard[2][2] && chessboard[0][0] != ' '){return chessboard[0][0]; //判断右斜线是否相同}if (chessboard[0][2] == chessboard[1][1] && chessboard[1][1] == chessboard[2][0] && chessboard[1][1] != ' '){return chessboard[0][2]; //判断左斜线是否相同}if (if_full(chessboard,row,col)) //判断是否平局,平局返回‘Q’{return 'Q';}return 'P';}
好了,今天就到这了。如有瑕疵,请多指教。