前言
此程序可进行棋盘扩展,实验结果将进行”5*5棋盘_连4棋赢“状态下的运行结果进行展示,可在game.h头文件对ROW和COL这两个宏进行行列数的随意更改,同样也可对”WIN“宏进行更改,实现连n子赢.
涉及文件
- test.c 代码的测试入口
- game.c 三子棋游戏实现涉及的功能函数
- game.h 进行函数声明,头文件引用,宏定义变量
基本实现逻辑:
game.h 头文件
-
#pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 3 #define COL 3 #define WIN 3 //初始化棋盘 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘 void DisplayBoard(char board[ROW][COL], int row, int col); //玩家下棋 void player_move(char board[ROW][COL], int row, int col); //电脑下棋 void computer_move(char board[ROW][COL], int row,int col); //判断输赢 //玩家赢——'*' //电脑赢--'#' //平局--'Q' //继续--'C' char is_win(char board[ROW][COL], int row, int col);
test.c源文件
-
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf("************************\n"); printf("******** 1.play ******\n"); printf("******** 2.exit ******\n"); printf("************************\n"); } void game() { char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL);//初始化棋盘 DisplayBoard(board, ROW, COL);//打印棋盘 char ret = 0; while (1) { //玩家下棋 player_move(board,ROW,COL); DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') { break; } //电脑下棋 computer_move(board,ROW,COL); DisplayBoard(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢了"); } else if (ret == '#') { printf("电脑赢了"); } else { printf("打平了"); } } void test() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请输入:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误\n"); break; } } while (input); } int main() { test(); return 0; }
game.c源文件
-
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void InitBoard(char board[ROW][COL],int row,int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } } void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf(" %c ", board[i][j]);//数据 if (j < col - 1) { printf("|"); } } printf("\n"); if (i < row - 1) { for (j = 0; j < col; j++) { printf("---");//分割行 if (j < col - 1) printf("|"); } } printf("\n"); } } void player_move(char board[ROW][COL], int row, int col) { printf("玩家输入:>"); int x = 0; int y = 0; while (1) { scanf("%d %d", &x, &y); if (x >= 1 && x <= col && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该坐标已被占用,请重新输入!\n"); } } else { printf("坐标非法\n"); } } } void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下棋:>\n"); int x = 0; int y = 0; while (1) { x = rand() % ROW;//0~2 y = rand() % COL;//0~2 if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } int is_full(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { 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; int j = 0; int count = 0; //行相同 for (i = 0; i < row; i++, count = 0) { for (j = 0; j < col - 1; j++) { if (board[i][j] == board[i][j + 1] && board[i][j] != ' ') { count++; } if (count == WIN-1) { return board[i][j]; } } } //列相同 for (j = 0; j < col; j++, count = 0) { for (i = 0; i < row - 1; i++) { if (board[i][j] == board[i+1][j] && board[i][j] != ' ') { count++; } if (count == WIN - 1) { return board[i][j]; } } } //斜向相同 //向下循环 int count1 = 0; for (i = 0; i < row; i -= (count1 - 1), count1 = 0, count = 0)//count1:消除内部循环对外部i的影响 { for (j = 0; i < row - 1 && j < col - 1; i++, j++) { if (board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ') { count++; } if (count == WIN - 1) { return board[i][j]; } count1++; } } count1 = 0; //斜向相同 //向上循环 for (j = 0; j < col - WIN + 1; j -= (count1 - 1), count1 = 0, count = 0)//count1:消除内部循环对外部i的影响 { for (i = 0; i < row - 1 && j < col - 1; i++, j++) { if ((board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ')|| //右下方向 (board[i][col - 1 - j] == board[i + 1][col - 2-j] && board[i][col - 1 - j] != ' ')) //左下方向 { count++; } if (count == WIN - 1) { return board[i][j]; } count1++; } } //平局 if (1 == is_full(board, row, col)) { return 'Q'; } //继续 return 'C'; }
实验结果:
-
键盘初始化
-
成功界面
- 棋盘扩展后状态(5*5棋盘_连4棋赢)
总结
- 程序为提高扩展性,便于后期维护,采用宏定义变量的方式对棋盘大小进行定义,进而有了”打印棋盘“过程,”判断输赢“过程中多次循环的出现,对其进行适应。虽然电脑下棋可谓人工智障,但还是有许多可借鉴之处的。