多文件编程:在编写代码的过程中不可能都把代码都放到一个文件里面,这里把游戏执行的代码和声明功能函数还有功能函数的实现分开编写,这样可以提高代码的可读性,方便修改代码,减少耦合,提高函数的复用性,界面简洁干净。
PS:这里把游戏的功能函数声明放在 game.h里面,把功能函数的实现写到
game.app里面,这里虽然文件名字可以不相同,但是最好相同,这样让人阅读代码的时候一眼就会看出来是一整个模块。
game.h
#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> //方便以后改棋盘
#define ROW 3 #define COL 3 //初始化棋盘 void init_board(char board[ROW][COL], int
row, int col); //打印棋盘 void dispaly_board(char board[ROW][COL],int row,int col);
//玩家走 void play_move(char board[ROW][COL], int row, int col, char n); //电脑下棋
void computer_move(char board[ROW][COL], int row, int col, char n); //判断输赢 char
IsWin(char board[ROW][COL], int row, int col);
game.cpp
#include"game.h" void init_board(char board[ROW][COL], int row, int col) { for
(int i = 0; i < ROW;i++) { for (int j = 0; j < COL;j++) { board[i][j] = ' '; }
} } //这种写法用ROW 和 COL 控制,以后想改棋盘大小就不用改动函数了。 void dispaly_board(char
board[ROW][COL], int row, int col) { for (int i = 0; i < ROW; i++) { for (int j
= 0; j < COL;j++) { printf(" %c ",board[i][j]); if (j < COL - 1) { printf("|");
} } printf("\n"); if (i < ROW - 1) { //控制printf("---");打印的行数,最后一行不打印 for (int k
= 0; k < COL; k++) { if (k < COL - 1) { //控制最后一列的打印 printf("---|"); } else {
printf("---"); } } } printf("\n"); } } void play_move(char board[ROW][COL], int
row, int col,char n) { int x = 0,y = 0; printf("玩家下棋:>\n"); while (1) {
printf("请输入坐标:>\n"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1
&& y <= col) { if (board[x - 1][y - 1]==' ') { board[x - 1][y - 1] = n; break;
} else { printf("已经有棋子,重新输入。\n"); } } else { printf("输入错误,重新输入。\n"); } } } void
computer_move(char board[ROW][COL],int row,int col,char n) { int x = 0, y = 0;
printf("玩家下棋:>\n"); while (1) { x = rand() % row; y = rand() % col; if
(board[x][y] == ' ') { board[x][y] = n; break; } } } int is_full(char
board[ROW][COL], int row, int col) { for (int i = 0; i < row;i++) { for (int j
= 0; j < col; j++) { if (board[i][j]==' ') { return 0; } } } return 1; } char
IsWin(char board[ROW][COL], int row, int col) { //判断行 for (int i = 0; i <
row;i++) { if (board[i][0]== board[i][1]&& board[i][1]== board[i][2]&&
board[i][2]!=' ') { return board[i][2]; } } //判断列 for (int j = 0; j < col; j++)
{ if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j]
!= ' ') { return board[2][j]; } } //判断对角线 if (board[0][0] == board[1][1] &&
board[1][1] == board[2][2] && board[2][2] != ' ') { return board[2][2]; } if
(board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != '
') { return board[2][0]; } if (is_full(board, row, col)==1) { return 'Q'; }
return 'C'; }
三子棋.cpp
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include"game.h" //界面
void menu() { printf("***************\n"); printf("**** 1.play ***\n");
printf("**** 2.exit ***\n"); printf("***************\n"); } void play() { char
ret = 0; char 棋盘[ROW][COL]={0}; init_board(棋盘, ROW, COL); //初始化棋盘
dispaly_board(棋盘, ROW, COL); //画出棋盘 while (1) { play_move(棋盘, ROW, COL, '*');
//玩家下棋 dispaly_board(棋盘, ROW, COL); ret = IsWin(棋盘, ROW, COL); if (ret!='C') {
break; } computer_move(棋盘, ROW, COL, '#');//电脑下棋 dispaly_board(棋盘, ROW, COL);
ret = IsWin(棋盘, ROW, COL); if (ret != 'C') { break; } } if (ret=='*') {
printf("玩家赢了。\n"); } else if (ret=='#'){ printf("电脑赢了。\n"); } else{
printf("平局。\n"); } } void game() { srand((unsigned int)time(NULL)); int select
= 0; do { menu(); printf("请选择:>\n"); scanf("%d",&select); switch (select) {
case 1: play(); system("pause"); system("cls"); break; case 2: exit(0); break;
default: printf("输入错误\n"); } } while (1); } int main() { game(); return 0; }
我们这里用二维数组来存三子棋的棋子,就是说相当于用二维数组当做三子棋的棋盘
,里面存的字符就是棋子。然后每次游玩的时候,相当于在数组中放上字符,当几个方向上的棋子相同了,就是字符都相等了,然后判断输赢。
这里电脑移动取的随机值。
这里要注意,写功能函数的时候不要把棋盘的大小写死,这样以后想改棋盘的时候要修改整个函数,提高了工作量。使用 #define ROW 3 ,以后想改
棋盘大小就动这两个的大小就行了。
为什么这里功能函数里面的判断不直接用宏定义的 ROW 和 COL
来做循环的条件判断呢,而是作为一个参数传入,这样不是多此一举吗。这是因为如果以后这个函数被使用到别的项目上以后,宏定义消失了还是要进行函数的修改,使用这种写法,直接把宏当做参数,不用动函数的内部结构。