前言
对很大多数初学者来说,三子棋这个小游戏的实现是一个不错挑战(痛并快乐着)接下来分享一下实现过程,希望大家多动手实践.
一、问题描述
用c语言来实现简单的三子棋游戏
二、基本流程
在写三子棋的代码之前,我们来看看实现这个游戏的逻辑:
1.对菜单的打印,菜单界面开始游戏或者退出;
2.对棋盘进行搭建及初始化;
3.玩家开始下棋以及判定(玩家输入行列坐标的方式来落子),'x’表示玩家落子;
4.电脑下棋;
5.判定胜负关系(输,赢,和棋),'q’表示和棋;
6.回到 步骤2 继续执行.
三、前期的准备工作
在实现复杂的代码的时候,为了使我们更加明确的知道每步具体的功能,我们可以配置不同的环境来存放不同功能的代码,这样可以使逻辑更加清晰:
插入图片
在test.c:文件中,游戏实现的函数在test.c中被引用;
game.c:函数的实现主要是在game.c文件中完成;
game.h:文件中包含了程序所需的各种头文件并且包换对实现游戏功能的各种函数的声明.
四、步骤
1.菜单的创建及玩家的选择
输入1:则开始游戏; 输入0;退出游戏 效果图如下:
void menu() { printf("------------------------------------\n"); printf("-------- 1.play -------\n"); printf("-------- 2.exit -------- \n"); printf("------------------------------------\n"); }
菜单写出来之后,自然而然我们要让玩家能够根据信息输入相应的数字进行游戏,效果图如下:
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; }
2.棋盘的搭建
在这里我们打印的是3*3的数组的形式,使用宏定义的有如下两个好处:
1.可以增加扩展性,如果之后想要修改棋盘的大小,只需要改变相应宏定义的数字即可;
2.方便大家后面更好的理解代码。
#define ROW 3 #define COL 3 //声明 void init_board(char board[ROW][COL], int row, int col);
3.棋盘初始化
初始化本质就是初始化开始创建的名为board的一个二维数组中的每个元素,在头文件中命名,在game.c中实现。
效果如下:
void init_board(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 init_board(char board[ROW][COL], int row, int col);
紧接着打印出我们的棋盘,代码如下:
void display_board(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) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("\n"); } } }
效果如下:
4.玩家下棋
玩家通过行列坐标来表示自己落子的位置。
注意事项:
1.玩家输入的信息要在坐标之内,注意行列的值;
2.玩家落子的时候要在空格的地方。
代码如下图:
void player_move(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家走:>\n"); while (1) { printf("请输入要下的坐标:>"); 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] = '*'; break; } else { printf("该坐标被占用,请重新输入\n"); } } else { printf("坐标非法,重新输入\n"); } } }
5.电脑下棋
由于电脑是随机产生的落子位置,‘#’是代表电脑落子的位置
void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下棋:>\n"); while (1) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
在对电脑进行随机化落子的时候我们用的是srand函数(初始化随机数生成器)
https://legacy.cplusplus.com/reference/cstdlib/srand/?kw=srand
6.判定结果
规则如下(自定义):
//玩家赢 - ‘*’
//电脑赢 - ‘#’
//平局了 - ‘Q’
//游戏继续 - ‘C’
if (ret == '*') { printf("玩家赢\n"); } else if (ret == '#') { printf("电脑赢\n"); } else if (ret == 'Q') { printf("平局\n"); } display_board(board, ROW, COL); }
判断胜败:
1.判断棋盘的行列;
2.判断对角线的情况
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]; } } for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ') { return board[0][i]; } } 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) == 1) { return 'Q'; } return 'C'; }
7.结果展示
输的情况暂干不出来。
五、总结以及代码
综上所述,三子棋这个游戏其实还是很好玩的,在开始设计之前我们一定要有一个总的框架(有个大体在开始上手),不要像无头苍蝇一样乱撞,最后希望大家都动手操作,只有多练才能明白!
game.c的代码如下:
#include "game.h" void init_board(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 display_board(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) { 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) { int x = 0; int y = 0; printf("玩家走:>\n"); while (1) { printf("请输入要下的坐标:>"); 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] = '*'; break; } else { printf("该坐标被占用,请重新输入\n"); } } else { printf("坐标非法,重新输入\n"); } } } void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下棋:>\n"); while (1) { int x = rand() % row; int y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } static 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]; } } for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ') { return board[0][i]; } } 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) == 1) { return 'Q'; } return 'C'; }
game.h的代码如下:
#pragma once #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 3 #define COL 3 //声明 void init_board(char board[ROW][COL], int row, int col); void display_board(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); char is_win(char board[ROW][COL], int row, int col);
text.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 ret = 0; char board[ROW][COL] = { 0 }; //全部空格 //初始化棋盘 init_board(board, ROW, COL); // display_board(board, ROW, COL); while (1) { //玩家下棋 player_move(board, ROW, COL); display_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') break; computer_move(board, ROW, COL); display_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') break; } //玩家赢 - '*' //电脑赢 - '#' //平局了 - 'Q' //游戏继续 - 'C' if (ret == '*') { printf("玩家赢\n"); } else if (ret == '#') { printf("电脑赢\n"); } else if (ret == 'Q') { printf("平局\n"); } display_board(board, ROW, COL); } 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; }