一、game.h
#pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 3 #define COL 3 //创建棋盘 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘 void DisplayBoard(char board[ROW][COL], int row, int col); //玩家移动 void PlayerMove(char board, int row,int col); //电脑移动 void ComputerMove(char board, int row, int col); //判断输赢 //玩家胜利'*' //电脑胜利'#' //平局'Q' //继续'C' char Is_win(char board, int row, int col); //判断棋盘是否满 int Is_full(char board, int row, int col);
二、game.c
#include"game.h" void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row ; i++) { int j = 0; for (j = 0; j < col ; j++) { board[i][j] = ' ' ; } } } void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row ; i++) { int j = 0; for (j = 0; j < col ; j++) { printf(" %c ", board[i][j]); if (j < col - 1) printf("|"); } printf("\n"); if (i < row - 1) { int j = 0; for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("\n"); } } } void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("请输入坐标,用空格分开:"); while (1) { scanf_s("%d %d", &x, &y); //坐标合法 if (x >= 1 && x <= row && y>=1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else printf("坐标已占用,请重新输入:"); } else printf("坐标不合法\n"); } } void ComputerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("电脑下棋\n"); while (1) { x = rand() % row; y = rand() % col; if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '#'; break; } } } int Is_full(char board[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 (board[i][j] == ' ') return 0; } } return 1; } char Is_win(char board[ROW][COL], int row, int col) { //行 int i = 0; for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') return board[i][0]; //列 int j = 0; for (j = 0; j < col; j++) { if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ') return board[0][j]; } } //对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') return board[1][1]; if(board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') return board[1][1]; //平局(棋盘满了) if (Is_full(board, ROW, COL)) { return 'Q'; } //游戏继续 return 'C'; }
三、test.c
#include"game.h" void menu() { printf("*****************************\n"); printf("****** 1. start ******\n"); printf("****** 0.exit ******\n"); printf("*****************************\n"); } void game() { char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); char ret = 0; while (1) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = Is_win(board, ROW, COL); if (ret != 'C') break; ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = Is_win(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') printf("玩家胜利\n"); else if (ret == '#') printf("电脑胜利\n"); else printf("平局\n"); } int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); scanf_s("%d", &input); switch (input) { case 1: printf("开始游戏\n"); game(); break; case 0: printf("游戏结束\n"); break; default: printf("请重新输入:\n"); break; } }while (input);//只有输入0,游戏才结束 return 0; }
四、思路构建
(一)主函数框架:
首先我想让这个游戏可以重复游玩,所以构建了一个do while循环,其次我需要给用户提供一个游戏菜单,供用户选择接下来的操作,所以一个menu()函数则是必需的啦。并且与之配套的需要switch与之搭配等,主函数的框架就是这么简单。
(二)封装的游戏函数框架:
(1)棋盘的构建:
为了让游戏可视化,我们需要创建一个棋盘并将其打印出来,我预想并最终设计的棋盘如图:
如果想以二维数组来实现该棋盘,很明显他的组成为:
第一行:三组“空格+数据+空格+|”,最后一个“|”不打印,我们把“空格+数据+空格”看为一个整体,把“|”看成一个整体,就得到第一行的初步逻辑。
第二行:三组“-+-+-+|”,同样的最后一个“|”不打印,同理,我们把“-+-+-”看为一个整体,把“|”看成一个整体。
那么按照上面分组的思路,我们可以把第一行与第二行看成一个整体,实际上就是打印三组由第一行与第二行构成的整体,并将第三组的第二行省略。
这就构成了整个棋盘构建的思路。
(2)玩家下棋:
我们把玩家落子规定为“*”,那么很明显需要用户输入坐标,之后我们需要按照用户给的坐标,将对应坐标的数据由“空格”改为“*”。
需要注意的是,我们需要判断用户输入的坐标是否合法,并且对应坐标的位置上有无棋子。
(3)电脑下棋:
我们把电脑落子规定为“#”,可以利用rand()函数,以时间戳生成随机数,并将其坐标%行(列)的方式来得到随机坐标,同理,和用户一样,我们需要判断对应坐标的位置上有无棋子。
(4)判断输赢:
那么如何来判断输赢呢?
输赢:很明显,如果相同的棋子以行,列,或者对角线的方式连成一线,那么就判定一方胜利。
平局:棋盘满。
游戏继续:如果未满足以上条件,我们需要让游戏继续。
这里很巧妙的一点是:我在设计函数的时候将判断输赢的函数设计返回值为char,如果玩家赢返回“*”,电脑赢返回“#”,所以判断胜利时,我们只需要返回board[x][y](此为连成线的其中一个元素),就知道了到底是玩家胜利还是电脑胜利了。平局返回“Q”,游戏继续返回“C”,那么对应的将game()函数中加入这一判断条件即可。
五、本篇你最应该学习到的
思路的构建,并整理出你期望实现的功能,根据功能逐步代码实现,调试的过程逐步优化。