Code of AI

[wrtn & ChatGPT] 윈도우OS에서 지뢰찾기 게임을 할 수 있도록 파이썬 코드를 만들어줘

별별AI 2023. 9. 20. 12:00
728x90

wrtn의 답변 : 

 

 

윈도우 OS에서 지뢰찾기 게임을 실행하기 위해서는 파이썬 코드만으로는 부족합니다. 윈도우 GUI를 구현하기 위해 PyQt 또는 Tkinter와 같은 라이브러리가 필요합니다.

아래는 Tkinter를 사용하여 윈도우 OS에서 실행할 수 있는 간단한 지뢰찾기 게임의 예시 코드입니다.

 


tkinter 설치 :

명령 크롬프트에서 pip install tk 입력

 

Collecting tk
  Downloading tk-0.1.0-py3-none-any.whl (3.9 kB)
Installing collected packages: tk
Successfully installed tk-0.1.0


 

import random
import tkinter as tk
from tkinter import messagebox

class MineSweeperGame:
    def __init__(self, rows, cols, num_mines):
        self.rows = rows
        self.cols = cols
        self.num_mines = num_mines
        self.board = [[' ' for _ in range(cols)] for _ in range(rows)]
        self.mine_positions = []
        
        # 폭탄 위치 랜덤 설정
        positions = random.sample(range(rows * cols), num_mines)
        
        for pos in positions:
            row = pos // cols
            col = pos % cols
            
            self.board[row][col] = '*'
            self.mine_positions.append((row, col))
        
    def start_game(self):
        window = tk.Tk()
        
        for i in range(self.rows):
            for j in range(self.cols):
                btn = tk.Button(window, text=' ', width=2,
                                command=lambda r=i, c=j: self.click_cell(r, c))
                btn.grid(row=i, column=j)
                
                btn.bind('<Button-3>', lambda e: self.flag_cell(e.widget))
                
                setattr(btn, 'row', i)
                setattr(btn, 'col', j)
                
                if (i,j) in self.mine_positions:
                    setattr(btn, 'is_mine', True)
                    
        window.mainloop()
    
    def click_cell(self, row_idx, col_idx):
        cell_value = self.board[row_idx][col_idx]
        
         if cell_value == '*':
             messagebox.showinfo('Game Over', '게임 오버! 폭탄을 밟았습니다.')
         else:
             adjacent_mines_count = 0
            
             # 주변 폭탄 개수 확인
             for dr in [-1, 0 ,1]:
                 for dc in [-1 ,0 ,1]:
                     if dr == 0 and dc == 0:
                         continue
                    
                     new_row_idx= row_idx + dr 
                     new_col_idx= col_idx + dc
                    
                     if (new_row_idx >= 0 and new_row_idx <self.rows and 
                         new_col_idx >= 0 and new_col_idx <self.cols and 
                         self.board[new_row_idx][new_col_Idx] == '*'):
                            
                            adjacent_mines_count += 1
                
             # 버튼 업데이트       
             button_id= getattr(getattr(btn.grid_info(),'children')[0], 'id')
            
             btn.config(text=str(adjacent_mines_count), state=tk.DISABLED)
            
              if adjacent_mines_count == 0 :
                  # 주변 셀 자동 클릭 처리 (재귀 호출)
                  for drin [-1 , 0 ,1]:
                      fo rdcin[-1 , 0 ,1]:
                          i fdr==oandd c==o :
                              continue
                        
                          n ew_ r ow_ idx=rowidx+dr 
                          n ew_ c ol_ idx=c o lidx+dc
                        
                          i fn ew_ r ow_ idx>=oandn ew_ r owidx< s elf. rowsandn ewc olidx>=oandn ewc olidx< s elf. co lsandgetattr( getattr( b tn.g rid_info(),' children')[i d], 'state')==tk.NORMAL:

                                s el f.click_cell(new_row_id x,new_co l_id x)

              # 승리 조건 확인         
              all_cells_revealed=True 
            
              fo ri nrange(s elf .rows ):
                  fo rcinrange(s elf .co ls ):
                      cell_v alue=s el f.boar d[r ][c ]
                    
                      i fc ell_valu e=='*'a ndgeta ttr(getattr( g tn.g rid_info(),' children')[i d],' state')==tk.NORMAL:

                            a ll_cel ls_revealed=False 
                            b reak 
            
               if all_cells_revealed :
                   messagebox.showinfo('Congratulations','축하합니다! 모든 지뢰를 찾았습니다.')
                   win.quit()

    def flag_cell(self, button):
         button.config(text='!', state=tk.DISABLED)

def play_game():
     rows=int(input("게임 보드의 행 수를 입력하세요: "))
     cols=int(input("게임 보드의 열 수를 입력하세요: "))
     nummines=int(input("지뢰 개수를 입력하세요: "))

     game=M ineSweeperGame(rows,col s,nummines )
     game.start_game()

play_game()

 


  File "c:\Python\mine_wrtn.py", line 45
    if cell_value == '*':
IndentationError: unexpected indent

 

실행 후, 오류 발생

 


ChatGPT에서 오류 수정 요청

 

import random
import tkinter as tk
from tkinter import messagebox

class MineSweeperGame:
    def __init__(self, rows, cols, num_mines):
        self.rows = rows
        self.cols = cols
        self.num_mines = num_mines
        self.board = [[' ' for _ in range(cols)] for _ in range(rows)]
        self.mine_positions = []
        
        # 폭탄 위치 랜덤 설정
        positions = random.sample(range(rows * cols), num_mines)
        
        for pos in positions:
            row = pos // cols
            col = pos % cols
            
            self.board[row][col] = '*'
            self.mine_positions.append((row, col))
        
    def start_game(self):
        window = tk.Tk()
        
        for i in range(self.rows):
            for j in range(self.cols):
                btn = tk.Button(window, text=' ', width=2,
                                command=lambda r=i, c=j: self.click_cell(r, c))
                btn.grid(row=i, column=j)
                
                btn.bind('<Button-3>', lambda e, btn=btn: self.flag_cell(btn))
                
                setattr(btn, 'row', i)
                setattr(btn, 'col', j)
                
                if (i, j) in self.mine_positions:
                    setattr(btn, 'is_mine', True)
                    
        window.mainloop()
    
    def click_cell(self, row_idx, col_idx):
        cell_value = self.board[row_idx][col_idx]
        
        if cell_value == '*':
            messagebox.showinfo('Game Over', '게임 오버! 폭탄을 밟았습니다.')
        else:
            adjacent_mines_count = 0
            
            # 주변 폭탄 개수 확인
            for dr in [-1, 0, 1]:
                for dc in [-1, 0, 1]:
                    if dr == 0 and dc == 0:
                        continue
                    
                    new_row_idx = row_idx + dr
                    new_col_idx = col_idx + dc
                    
                    if (0 <= new_row_idx < self.rows and 
                        0 <= new_col_idx < self.cols and 
                        self.board[new_row_idx][new_col_idx] == '*'):
                        
                        adjacent_mines_count += 1
                
            # 버튼 업데이트       
            btn = getattr(getattr(btn.grid_info(), 'children')[0], 'id')
            btn.config(text=str(adjacent_mines_count), state=tk.DISABLED)
            
            if adjacent_mines_count == 0:
                # 주변 셀 자동 클릭 처리 (재귀 호출)
                for dr in [-1, 0, 1]:
                    for dc in [-1, 0, 1]:
                        if dr == 0 and dc == 0:
                            continue
                        
                        new_row_idx = row_idx + dr
                        new_col_idx = col_idx + dc
                        
                        if (0 <= new_row_idx < self.rows and 
                            0 <= new_col_idx < self.cols and 
                            getattr(getattr(btn.grid_info(), 'children')[0], 'state') == tk.NORMAL):
                            
                            self.click_cell(new_row_idx, new_col_idx)
            
            # 승리 조건 확인         
            all_cells_revealed = True 
            
            for i in range(self.rows):
                for j in range(self.cols):
                    cell_value = self.board[i][j]
                    
                    if cell_value == '*' and getattr(getattr(btn.grid_info(), 'children')[0], 'state') == tk.NORMAL:
                        all_cells_revealed = False
                        break 
            
            if all_cells_revealed:
                messagebox.showinfo('Congratulations', '축하합니다! 모든 지뢰를 찾았습니다.')
                window.quit()

    def flag_cell(self, button):
        button.config(text='!', state=tk.DISABLED)

def play_game():
    rows = int(input("게임 보드의 행 수를 입력하세요: "))
    cols = int(input("게임 보드의 열 수를 입력하세요: "))
    num_mines = int(input("지뢰 개수를 입력하세요: "))

    game = MineSweeperGame(rows, cols, num_mines)
    game.start_game()

play_game()

 


위 코드에서 주요 수정 사항은 다음과 같습니다:

btn.bind('<Button-3>', lambda e, btn=btn: self.flag_cell(btn)): btn을 flag_cell 함수로 전달하기 위해 람다 함수에 btn=btn 매개변수를 추가했습니다.

if (new_row_idx >= 0 and new_row_idx < self.rows and new_col_idx >= 0 and new_col_idx < self.cols and self.board[new_row_idx][new_col_idx] == '*'):: 행과 열 인덱스를 확인할 때 조건문을 수정하여 오류를 수정했습니다.

if all_cells_revealed:: 승리 조건 확인 부분에서 버튼과 연관된 조건을 수정하여 모든 지뢰를 찾았을 때 게임을 종료하도록 수정했습니다.

 


 

 

오류 수정 후에 위처럼 실행되는 것을 확인

 

지뢰가 있는 위치를 선택하면 위처럼 문구 출력

 

디테일한 설정들은 수정할 필요가 있음. 

728x90