C语言三子棋小游戏

简介: C语言三子棋小游戏

1.游戏

今天我们写的代码分为三个文件来写,分别是:

game.h 用来放函数的声明

game.c 用来放函数的定义

test.c 游戏的主体文件


大概介绍:

进入游戏,首先定义棋盘,对棋盘进行初始化。然后就是进入下棋的过程了,玩家是先手,玩家和电脑要不断重复地下棋,所以要在循环体内进行,玩家下棋,电脑下棋,判断输赢,和打印棋盘都是用函数来完成的

void game()
{
  char board[ROW][COL];
  InitBoard(board, ROW, COL);
  //打印棋盘
  DisPlayBoard(board, ROW, COL);
  //下棋
  char ret = 0;
  while(1)
  {
    //玩家下棋
    PlayerMove(board, ROW, COL);
    //打印棋盘
    DisPlayBoard(board, ROW, COL);
    //判断输赢
    ret=IsWin(board, ROW, COL);
    if (ret != 'C')
    {
      break;
    }
    //电脑下棋
    ComputeMove(board, ROW, COL);
    //打印棋盘
    DisPlayBoard(board, ROW, COL);
    //判断输赢
    ret=IsWin(board, ROW, COL);
    if (ret != 'C')
    {
      break;
    }
  }
  if (ret == '*')
  {
    printf("玩家赢\n");
  }
  else if (ret == '#')
  {
    printf("电脑赢\n");
  }
  else
  {
    printf("平局\n");
  }
}


下面开始我们的学习吧:

2.函数部分

下面要介绍的是函数部分,因为游戏的代码比较长,将某些功能封装成函数,可以减少代码的重复量。

//菜单
void menu();
//游戏
void game();
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisPlayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputeMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col);

2.1.菜单

菜单的实现很简单,用户输入1开始游戏,输入0退出游戏

void menu()
{
  printf("*********************\n");
  printf("******  1.play ******\n");
  printf("******  0.exit ******\n");
  printf("*********************\n");
}

2.2.初始化棋盘

初始化棋盘就是在游戏开始之前将棋盘数组初始化为空格

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] = ' ';
    }
  }
}

2.3.打印棋盘

打印棋盘的过程是比较麻烦的,下图是棋盘的效果展示图:

在一个3*3的棋盘中,我们不仅要打印棋盘的数线,也要打印棋盘的横线,还要考虑棋子位置等问题。

 

void DisPlayBoard(char board[ROW][COL], int row, int col)
{
  int i = 0, 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");
    }
  }
}

2.4.玩家下棋

玩家下棋的时候,需要判断输入的坐标是否合法,如果不合法,就需要重复输入。我们用‘*’来表示玩家下的棋子,用‘#’表示电脑下的棋子。

void PlayerMove(char board[ROW][COL], int row, int col)
{
  int x = 0, 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");
    } 
  }
}


2.5.电脑下棋

电脑下棋,需要是电脑产生2个随机数,如何是电脑产生的随机数在棋盘的大小之内呢?

我们可以使电脑产生的随机数对行和列相除取余,如果产生的随机数不合法,就需要让电脑重复产生新的随机数,直到坐标合法

void ComputeMove(char board[ROW][COL], int row, int col)
{
  int x = 0, y = 0;
  printf("电脑下棋:>\n");
  while(1)
  {
    x = rand() % row;
    y = rand() % col;
    if (board[x][y] == ' ')
    {
      board[x][y] = '#';
      break;
    }
  }
}

2.6.判断输赢

判断输赢不仅要判断每一行,每一列,还要判断每一列

我们规定:

玩家赢 返回 '*'

电脑赢 返回 '#'

平局 返回 'Q'

继续 返回 'C'

这样当一方赢了后我们直接返回赢的一方的某个棋子即可

char IsWin(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][1];
    }
  }
  //列
  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[0][0] != ' ')
  {
    return board[0][0];
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
  {
    return board[0][2];
  }
  //平局
  if (IsFull(board, ROW, COL)==1)
  {
    return 'Q';
  }
  //继续
  return 'C';
}


2.7.判断棋盘是否已满

在每下完一步棋子后,都需要判断棋盘是否已满,满了的话游戏肯定是不能继续下去的

int IsFull(char board[ROW][COL], int row, int col)
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
      if (board[i][j] == ' ')
        return 0;
    }
  }
  return 1;
}


3.完整代码展示

game.h文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//菜单
void menu();
//游戏
void game();
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisPlayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputeMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//判断棋盘是否满了
int IsFull(char board[ROW][COL], int row, int col);

game.c文件

#include"game.h"
void menu()
{
  printf("*********************\n");
  printf("******  1.play ******\n");
  printf("******  0.exit ******\n");
  printf("*********************\n");
}
//初始化棋盘为空格
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, 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 PlayerMove(char board[ROW][COL], int row, int col)
{
  int x = 0, 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 ComputeMove(char board[ROW][COL], int row, int col)
{
  int x = 0, y = 0;
  printf("电脑下棋:>\n");
  while(1)
  {
    x = rand() % row;
    y = rand() % col;
    if (board[x][y] == ' ')
    {
      board[x][y] = '#';
      break;
    }
  }
}
int IsFull(char board[ROW][COL], int row, int col)
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
      if (board[i][j] == ' ')
        return 0;
    }
  }
  return 1;
}
//玩家赢-'*'
//电脑赢-'#'
//平局-'Q'
//继续-'C'
char IsWin(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][1];
    }
  }
  //列
  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[0][0] != ' ')
  {
    return board[0][0];
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
  {
    return board[0][2];
  }
  //平局
  if (IsFull(board, ROW, COL)==1)
  {
    return 'Q';
  }
  //继续
  return 'C';
}

test.c文件

#include"game.h"
void game()
{
  char board[ROW][COL];
  InitBoard(board, ROW, COL);
  //打印棋盘
  DisPlayBoard(board, ROW, COL);
  //下棋
  char ret = 0;
  while(1)
  {
    //玩家下棋
    PlayerMove(board, ROW, COL);
    //打印棋盘
    DisPlayBoard(board, ROW, COL);
    //判断输赢
    ret=IsWin(board, ROW, COL);
    if (ret != 'C')
    {
      break;
    }
    //电脑下棋
    ComputeMove(board, ROW, COL);
    //打印棋盘
    DisPlayBoard(board, ROW, COL);
    //判断输赢
    ret=IsWin(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();
    printf("请选择:->");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("玩游戏\n");
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,重新选择\n");
      break;
    }
  } while (input);
  return 0;
}

下面是玩游戏的过程:


哈哈,是电脑赢得了本次游戏,如果感到不过瘾的话可以再来一把,哈哈哈


总结:今天我们学习了三子棋小游戏,使用了多文件编程的形式,别看一个简简单单的小游戏,代码实现起来也没有那么容易呢,如果我写的有什么的不好之处,请在文章下方给出你宝贵的意见。如果觉得我写的好的话请点个赞赞和关注哦~😘


目录
相关文章
|
27天前
|
C语言
C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
54 0
|
9天前
|
存储 编译器 C语言
|
9天前
|
存储 C语言
【C语言】猜数字小游戏
C语言实现猜数字小游戏
14 2
【C语言】猜数字小游戏
|
20天前
|
程序员 C语言
C语言小游戏之猜数字
C语言小游戏之猜数字
18 5
|
19天前
|
C语言
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
11 1
|
21天前
|
C语言
C语言小游戏的源代码
C语言小游戏的源代码
|
24天前
|
存储 C语言
三子棋(C语言版)
三子棋(C语言版)
|
2月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
32 1
|
2月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
31 1
|
1月前
|
程序员 C语言 索引
【️C语言-游戏设置】---三子棋(N满)
【️C语言-游戏设置】---三子棋(N满)