TCHAR,大小写敏感/不敏感的KMP算法

本文深入讲解了KMP算法的实现细节,包括如何构建next数组来提高字符串匹配效率,并提供了大小写敏感及不敏感两种情况下的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// ********************************* //
// kmp by Ceja
// ********************************* //

#include <tchar.h>


// kmp ==============
inline int* GetNextVal_i(const TCHAR *s, int &len);
inline int* GetNextVal(const TCHAR *s, int &len)
{
 len = (int)_tcslen(s);
 int *next = new int[len];
 int i = 0;
 int j = -1;
 next[0] = -1;
 while(i<len-1)//注意这里跟KMP函数里面的不同
 {
  if(j==-1 || s[i]==s[j])
  {
  ++i;
  ++j;
  next[i] = j;
  }
  else
  {
  j = next[j];
  }
 }
 return next;
}

// kmp 算法, 大小写敏感
inline int KMP(const TCHAR *s, const TCHAR *t)
{
 int slen,tlen;
 int i,j;
 int *next = GetNextVal(t, tlen);
 slen = (int)_tcslen(s);
 i = 0;
 j = 0;
 while(i<slen && j<tlen)
 {
  if(j==-1 || s[i]==t[j])
  {
  ++i;
  ++j;
  }
  else
  {
  j = next[j];
  }
 }

 delete[] next;

 if(j==tlen)
  return i - tlen;
 return -1;
}

// kmp 算法, 大小写不敏感
inline int KMP_i(const TCHAR *s, const TCHAR *t)
{
 int slen,tlen;
 int i,j;
 int *next = GetNextVal_i(t, tlen);
 slen = (int)_tcslen(s);
 i = 0;
 j = 0;
 while(i<slen && j<tlen)
 {
  if(j==-1 || ( ((_T('a') <= s[i] && _T('z') >= s[i])?(s[i] - 32):s[i]) == ((_T('a') <= t[j] && _T('z') >= t[j])?(t[j] - 32):t[j])))
  {
  ++i;
  ++j;
  }
  else
  {
  j = next[j];
  }
 }

 delete[] next;

 if(j==tlen)
  return i - tlen;
 return -1;
}

inline int* GetNextVal_i(const TCHAR *s, int &len)
{
 len = (int)_tcslen(s);
 int *next = new int[len];
 int i = 0;
 int j = -1;
 next[0] = -1;
 while(i<len-1)//注意这里跟KMP函数里面的不同
 {
  if(j==-1 || ( ((_T('a') <= s[i] && _T('z') >= s[i])?(s[i] - 32):s[i]) == ((_T('a') <= s[j] && _T('z') >= s[j])?(s[j] - 32):s[j])))
  {
  ++i;
  ++j;
  next[i] = j;
  }
  else
  {
  j = next[j];
  }
 }
 return next;
}



/// ***** end of kmp

将代码数组部分修改为链表 #include <graphics.h> // EasyX图形库 #include <conio.h> // 控制台输入输出 #include <string> // 字符串处理 #include <ctime> // 时间函数 #include <cmath> // 数学函数 #include <mmsystem.h> // 多媒体支持 #pragma comment(lib, "winmm.lib") // 多媒体库链接 using namespace std; // 游戏常量定义 const int PASS_COUNT = 8; // 总关卡数 const int WINDOW_WIDTH = 953; // 窗口宽度 const int WINDOW_HEIGHT = 453; // 窗口高度 const int PUZZLE_WIDTH = 600; // 拼图区域宽度 const int PUZZLE_HEIGHT = 450; // 拼图区域高度 const COLORREF BG_COLOR = LIGHTGREEN; // 背景颜色 // 拼图块结构体 struct PuzzlePiece { IMAGE image; // 图像对象 int gridX; // 网格X坐标 int gridY; // 网格Y坐标 }; // 游戏框架类 class GameFramework { public: GameFramework(); // 构造函数 void DrawBackground(); // 绘制背景 void ShowStartMenu(); // 显示开始菜单 }; // 拼图游戏类 class PuzzleGame { private: IMAGE fullImage; // 完整图像 PuzzlePiece** puzzlePieces; // 拼图块数组 int gameState; // 游戏状态 (0:选择难度, 1:设置拼图, 2:显示拼图, 3:游戏进行中) int difficulty; // 难度级别 (3:3x3, 4:4x4, 5:5x5) int currentLevel; // 当前关卡 (0-7) int pieceWidth; // 拼图块宽度 int pieceHeight; // 拼图块高度 string imagePath; // 图片路径 int emptyX, emptyY; // 空白块位置 int** positionMap; // 位置映射表 public: PuzzleGame(); // 构造函数 ~PuzzleGame(); // 析构函数 void Run(); // 游戏主循环 void SetDifficulty(); // 设置难度 void SetupPuzzle(); // 设置拼图 void DrawPuzzle(); // 绘制拼图 void HandleMouse(); // 处理鼠标事件 void MovePiece(int gridX, int gridY); // 移动拼图块 void CheckCompletion(); // 检查是否完成 void ShufflePuzzle(); // 打乱拼图 }; // 游戏框架构造函数 GameFramework::GameFramework() { initgraph(WINDOW_WIDTH, WINDOW_HEIGHT); // 初始化图形窗口 setbkcolor(BG_COLOR); // 设置背景颜色 cleardevice(); // 清屏 } // 绘制渐变背景 void GameFramework::DrawBackground() { float hue = 70.0f; // 色调 float saturation = -2.2555f; // 饱和度 float lightness = 0.525617f; // 亮度 BeginBatchDraw(); // 开始批量绘制 for (int y = 0; y < WINDOW_HEIGHT; y++) { lightness += 0.000000085f; // 亮度渐变 saturation -= 0.0013f; // 饱和度渐变 setlinecolor(HSLtoRGB(hue, saturation, lightness)); // 设置线条颜色 line(0, y, WINDOW_WIDTH, y); // 绘制水平线 } EndBatchDraw(); // 结束批量绘制 } // 显示开始菜单 void GameFramework::ShowStartMenu() { setbkmode(TRANSPARENT); // 设置透明背景 settextcolor(BLUE); // 设置文本颜色 // 显示游戏标题 settextstyle(30, 0, _T("华文行楷")); outtextxy(230, 85, _T("欢迎来到拼图游戏")); // 显示难度选择提示 settextstyle(23, 0, _T("华文行楷")); outtextxy(300, 170, _T("选择游戏难度:")); outtextxy(300, 210, _T("<A> 简单 (3x3)")); outtextxy(300, 270, _T("<B> 中等 (4x4)")); outtextxy(300, 330, _T("<C> 困难 (5x5)")); // 绘制菜单边框 setlinestyle(PS_SOLID, 5, NULL); setlinecolor(BLUE); rectangle(200, 50, 600, 400); line(200, 150, 600, 150); } // 拼图游戏构造函数 PuzzleGame::PuzzleGame() { gameState = 0; // 初始状态:选择难度 difficulty = 0; // 未选择难度 currentLevel = 0; // 初始关卡 imagePath = "Res\\00.jpg"; // 初始图片路径 pieceWidth = 0; // 初始拼图块宽度 pieceHeight = 0; // 初始拼图块高度 emptyX = 0; // 空白块X位置 emptyY = 0; // 空白块Y位置 puzzlePieces = nullptr; // 拼图块数组 positionMap = nullptr; // 位置映射表 } // 拼图游戏析构函数 PuzzleGame::~PuzzleGame() { // 释放拼图块数组内存 if (puzzlePieces && difficulty > 0) { for (int i = 0; i < difficulty; i++) { delete[] puzzlePieces[i]; } delete[] puzzlePieces; } // 释放位置映射表内存 if (positionMap && difficulty > 0) { for (int i = 0; i < difficulty; i++) { delete[] positionMap[i]; } delete[] positionMap; } } // 游戏主循环 void PuzzleGame::Run() { switch (gameState) { case 0: // 选择难度 SetDifficulty(); break; case 1: // 设置拼图 SetupPuzzle(); break; case 2: // 显示拼图 DrawPuzzle(); break; case 3: // 游戏进行中 HandleMouse(); CheckCompletion(); break; default: break; } } // 设置游戏难度 void PuzzleGame::SetDifficulty() { if (kbhit()) { // 检测键盘输入 char input = getch(); // 获取按键 mciSendString(_T("play Res\\key.wav"), NULL, 0, NULL); // 播放按键音效 switch (input) { case 'a': case 'A': difficulty = 3; break; // 简单难度 case 'b': case 'B': difficulty = 4; break; // 中等难度 case 'c': case 'C': difficulty = 5; break; // 困难难度 default: return; // 无效输入 } gameState = 1; // 进入设置拼图状态 } } // 设置拼图 void PuzzleGame::SetupPuzzle() { // 加载完整图像 TCHAR imgPath[256]; _stprintf_s(imgPath, _T("%S"), imagePath.c_str()); loadimage(&fullImage, imgPath, PUZZLE_WIDTH, PUZZLE_HEIGHT); // 计算拼图块尺寸 pieceWidth = PUZZLE_WIDTH / difficulty; pieceHeight = PUZZLE_HEIGHT / difficulty; // 创建拼图块数组 puzzlePieces = new PuzzlePiece * [difficulty]; for (int i = 0; i < difficulty; i++) { puzzlePieces[i] = new PuzzlePiece[difficulty]; } // 创建位置映射表 positionMap = new int* [difficulty]; for (int i = 0; i < difficulty; i++) { positionMap[i] = new int[difficulty]; for (int j = 0; j < difficulty; j++) { positionMap[i][j] = i * difficulty + j; } } // 设置工作图像为完整图像 SetWorkingImage(&fullImage); // 分割图像为拼图块 for (int i = 0; i < difficulty; i++) { for (int j = 0; j < difficulty; j++) { // 跳过右下角最后一块(空白块) if (i == difficulty - 1 && j == difficulty - 1) { continue; } // 获取拼图块图像 getimage(&puzzlePieces[i][j].image, j * pieceWidth, i * pieceHeight, pieceWidth - 3, pieceHeight - 3); // 设置初始位置 puzzlePieces[i][j].gridX = j; puzzlePieces[i][j].gridY = i; } } // 创建空白拼图块 puzzlePieces[difficulty - 1][difficulty - 1].image.Resize(pieceWidth - 3, pieceHeight - 3); SetWorkingImage(&puzzlePieces[difficulty - 1][difficulty - 1].image); // 绘制空白块的渐变背景 float hue = 50.0f; float saturation = -3.2555f; float lightness = 0.525617f; for (int y = 0; y < pieceHeight; y++) { lightness += 0.000000085f; saturation -= 0.0015f; setlinecolor(HSLtoRGB(hue, saturation, lightness)); line(0, y, pieceWidth, y); } // 设置空白块位置 puzzlePieces[difficulty - 1][difficulty - 1].gridX = difficulty - 1; puzzlePieces[difficulty - 1][difficulty - 1].gridY = difficulty - 1; emptyX = difficulty - 1; emptyY = difficulty - 1; // 恢复默认工作图像 SetWorkingImage(); // 打乱拼图 ShufflePuzzle(); gameState = 2; // 进入显示拼图状态 } // 绘制拼图 void PuzzleGame::DrawPuzzle() { // 清空拼图区域 setfillcolor(BG_COLOR); solidrectangle(0, 0, PUZZLE_WIDTH, PUZZLE_HEIGHT); // 绘制所有拼图块 for (int i = 0; i < difficulty; i++) { for (int j = 0; j < difficulty; j++) { // 跳过空白块 if (i == emptyY && j == emptyX) { continue; } // 获取拼图块的实际位置 int actualX = puzzlePieces[i][j].gridX; int actualY = puzzlePieces[i][j].gridY; // 绘制拼图块 putimage(actualX * pieceWidth + 3, actualY * pieceHeight + 3, &puzzlePieces[i][j].image); } } // 绘制完整图像预览 IMAGE preview; TCHAR imgPath[256]; _stprintf_s(imgPath, _T("%S"), imagePath.c_str()); loadimage(&preview, imgPath, 300, 225); setbkmode(TRANSPARENT); settextstyle(23, 0, _T("华文行楷")); settextcolor(BLUE); outtextxy(740, 70, _T("完整图像")); putimage(630, 100, &preview); // 显示当前关卡信息 TCHAR levelInfo[256]; _stprintf_s(levelInfo, _T("第 %d / %d 关"), currentLevel + 1, PASS_COUNT); outtextxy(730, 400, levelInfo); // 显示游戏状态 outtextxy(700, 350, _T("当前状态: 游戏中")); gameState = 3; // 进入游戏进行中状态 } // 处理鼠标事件 void PuzzleGame::HandleMouse() { if (MouseHit()) { // 检测鼠标事件 MOUSEMSG mouseMsg = GetMouseMsg(); // 获取鼠标消息 if (mouseMsg.uMsg == WM_LBUTTONDOWN) { // 左键点击 mciSendString(_T("play Res\\key.wav"), NULL, 0, NULL); // 播放按键音效 // 计算点击的网格坐标 int gridX = mouseMsg.x / pieceWidth; int gridY = mouseMsg.y / pieceHeight; // 检查点击位置是否有效 if (gridX < 0 || gridX >= difficulty || gridY < 0 || gridY >= difficulty) { return; } // 检查是否可以移动(与空白块相邻) bool canMove = false; if (gridX == emptyX) { if (abs(gridY - emptyY) == 1) canMove = true; } else if (gridY == emptyY) { if (abs(gridX - emptyX) == 1) canMove = true; } if (canMove) { MovePiece(gridX, gridY); // 移动拼图块 } } } } // 移动拼图块 void PuzzleGame::MovePiece(int gridX, int gridY) { // 找出点击的拼图块在数组中的位置 int pieceIndex = positionMap[gridY][gridX]; int pieceRow = pieceIndex / difficulty; int pieceCol = pieceIndex % difficulty; // 更新位置映射表 positionMap[emptyY][emptyX] = pieceIndex; positionMap[gridY][gridX] = difficulty * difficulty - 1; // 交换拼图块位置 puzzlePieces[pieceRow][pieceCol].gridX = emptyX; puzzlePieces[pieceRow][pieceCol].gridY = emptyY; // 更新空白块位置 emptyX = gridX; emptyY = gridY; // 重绘拼图 DrawPuzzle(); } // 检查是否完成拼图 void PuzzleGame::CheckCompletion() { bool completed = true; // 检查所有拼图块是否在正确位置 for (int i = 0; i < difficulty; i++) { for (int j = 0; j < difficulty; j++) { if (puzzlePieces[i][j].gridX != j || puzzlePieces[i][j].gridY != i) { completed = false; break; } } if (!completed) break; } // 如果完成当前关卡 if (completed) { // 显示完整图像 putimage(0, 0, &fullImage); // 显示完成信息 settextstyle(30, 0, _T("华文行楷")); settextcolor(GREEN); outtextxy(700, 350, _T("恭喜过关!")); FlushBatchDraw(); // 刷新屏幕 // 播放胜利音效 mciSendString(_T("play Res\\胜利.mp3"), NULL, 0, NULL); Sleep(3000); // 暂停3秒 // 进入下一关 currentLevel++; if (currentLevel < PASS_COUNT) { // 更新图片路径 char levelDigit1 = '0' + (currentLevel / 10); char levelDigit2 = '0' + (currentLevel % 10); imagePath[4] = levelDigit1; imagePath[5] = levelDigit2; // 重置游戏状态 gameState = 1; // 释放当前拼图资源 for (int i = 0; i < difficulty; i++) { delete[] puzzlePieces[i]; delete[] positionMap[i]; } delete[] puzzlePieces; delete[] positionMap; puzzlePieces = nullptr; positionMap = nullptr; } else { // 所有关卡完成 cleardevice(); settextstyle(50, 0, _T("华文行楷")); outtextxy(220, 200, _T("恭喜你完成所有关卡!")); outtextxy(300, 300, _T("游戏结束")); FlushBatchDraw(); Sleep(5000); gameState = 4; // 游戏结束状态 } } } // 打乱拼图 void PuzzleGame::ShufflePuzzle() { // 方向数组 (上, 左, 下, 右) const int dx[4] = { 0, -1, 0, 1 }; const int dy[4] = { -1, 0, 1, 0 }; srand(static_cast<unsigned int>(time(NULL))); // 随机种子 // 第一阶段:螺旋移动 int steps = difficulty * 2; // 移动步数 int direction = 0; // 初始方向 for (int i = 0; i < steps; i++) { int newX = emptyX + dx[direction]; int newY = emptyY + dy[direction]; // 检查新位置是否有效 if (newX >= 0 && newX < difficulty && newY >= 0 && newY < difficulty) { // 移动拼图块 int pieceIndex = positionMap[newY][newX]; int pieceRow = pieceIndex / difficulty; int pieceCol = pieceIndex % difficulty; // 更新位置映射表 positionMap[emptyY][emptyX] = pieceIndex; positionMap[newY][newX] = difficulty * difficulty - 1; // 交换拼图块位置 puzzlePieces[pieceRow][pieceCol].gridX = emptyX; puzzlePieces[pieceRow][pieceCol].gridY = emptyY; // 更新空白块位置 emptyX = newX; emptyY = newY; } // 改变方向 direction = (direction + 1) % 4; } // 第二阶段:随机移动 int shuffleCount = difficulty * 30; // 随机移动次数 for (int i = 0; i < shuffleCount; i++) { int dir = rand() % 4; // 随机方向 int newX = emptyX + dx[dir]; int newY = emptyY + dy[dir]; // 检查新位置是否有效 if (newX >= 0 && newX < difficulty && newY >= 0 && newY < difficulty) { // 移动拼图块 int pieceIndex = positionMap[newY][newX]; int pieceRow = pieceIndex / difficulty; int pieceCol = pieceIndex % difficulty; // 更新位置映射表 positionMap[emptyY][emptyX] = pieceIndex; positionMap[newY][newX] = difficulty * difficulty - 1; // 交换拼图块位置 puzzlePieces[pieceRow][pieceCol].gridX = emptyX; puzzlePieces[pieceRow][pieceCol].gridY = emptyY; // 更新空白块位置 emptyX = newX; emptyY = newY; } } } // 主函数 int main() { // 初始化游戏框架 GameFramework gameFramework; gameFramework.DrawBackground(); gameFramework.ShowStartMenu(); // 初始化拼图游戏 PuzzleGame puzzleGame; // 开启批量绘制 BeginBatchDraw(); // 游戏主循环 while (true) { puzzleGame.Run(); // 运行游戏逻辑 // 检测ESC键退出 if (kbhit() && getch() == 27) { break; } FlushBatchDraw(); // 刷新屏幕 Sleep(10); // 降低CPU占用 } // 结束批量绘制 EndBatchDraw(); // 关闭图形窗口 closegraph(); return 0; }
最新发布
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值