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;
}

下面是玩游戏的过程:


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


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


目录
相关文章
|
1月前
|
C语言
【C语言】猜数字小游戏的一步一步实现2
【C语言】猜数字小游戏的一步一步实现
|
1月前
|
算法 C语言
【C语言】猜数字小游戏的一步一步实现1
【C语言】猜数字小游戏的一步一步实现
|
2月前
|
算法 C语言 C++
【C语言实战项目】三子棋游戏
【C语言实战项目】三子棋游戏
32 1
|
2月前
|
C语言
C语言之三子棋小游戏
C语言之三子棋小游戏
|
2月前
|
C语言
用c语言实现三子棋
用c语言实现三子棋
12 0
|
2月前
|
算法 编译器 C语言
C语言猜数字小游戏(也包含python实现的用法)
本文基于VS2022、pycharm和前面的知识,写一个凭借分支与循环的小游戏,比如: 写一个猜数字游戏 游戏要求: 电脑自动生成1~100的随机数 玩家猜数字,猜数的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束 在pyhton中生成随机数是比较简单的,可以直接导入random的包,直接生成随机数,导致写猜数字小游戏变成了判读语句和循环语句嵌套就能写出来,所以我不做过多的介绍了,可以直接看后面的代码展示,想了解更多的python可看python的基础知识,这里面有我在学习python的过程中写的笔记
33 0
|
1月前
|
C语言
爱上C语言:扫雷小游戏,展开一片功能实现
爱上C语言:扫雷小游戏,展开一片功能实现
爱上C语言:扫雷小游戏,展开一片功能实现
|
1月前
|
人工智能 机器人 测试技术
【C语言】C语言实现猜单词小游戏(源码+报告)【独一无二】
【C语言】C语言实现猜单词小游戏(源码+报告)【独一无二】
|
2月前
|
C语言
三子棋c语言讲解
三子棋c语言讲解
|
2月前
|
存储 定位技术 C语言
基于C语言实现扫雷小游戏
本文介绍了使用C语言实现扫雷小游戏的过程。扫雷是一款经典的单机游戏,玩家需要通过点击方格来揭示数字或地雷,最终清除所有非地雷方格。实现过程中,首先定义了游戏所需的数据结构,如游戏地图、玩家信息等。然后,实现了游戏的初始化、渲染、输入处理等核心功能。在游戏逻辑方面,处理了点击事件、数字计算和胜负判断等。通过不断优化和完善,最终完成了基于C语言的扫雷小游戏实现,为玩家提供了一种简单有趣的游戏体验。
25 0