Skip to content

algorithm problem 2

Jongbin Oh edited this page Jun 8, 2013 · 1 revision

C++ 버전

  • Presentation error랍니다 ㅠㅠ [itmentor]

      /* @JUDGE_ID:itmentor 110102 C "test" */
      
      /* @BEGIN_OF_SOURCE_CODE */
      
      #ifdef _UNIT_TEST_
      	#include <UnitTest++.h>
      	#include <TestReporterStdout.h>
      #endif
      
      #include <iostream>
      #include <vector>
      #include <cmath>
      
      typedef std::vector< int >  Line;
      typedef std::vector< Line >  Array;
      
      const int MINE = -1;
      
      void createMap( int width, int height, Array& arr )
      {
      	arr.clear();
      	for(int i = 0 ; i < height ; i++ )
      		arr.push_back( Line (width, 0) );
      }
      
      void addMine( int xIndex, int yIndex, Array& arr )
      {
      	if( arr[yIndex][xIndex] == MINE )
      		return;
      
      	arr[yIndex][xIndex] = MINE;	//mine
      
      	for(int y = 0 ; y < arr.size() ; y++ )
      	{
      		for(int x = 0 ; x < arr[y].size() ; x++ )
      		{
      			float xDiff = xIndex - x;
      			float yDiff = yIndex - y;
      
      			float distance = sqrt( xDiff*xDiff + yDiff*yDiff );
      
      			if( 1.0f <= distance && distance <= sqrt(2.0f) )
      			{
      				if( arr[y][x] != MINE )
      					arr[y][x]++;
      			}
      		}
      	}	
      }
      
      int main()
      {
      #ifdef _UNIT_TEST_
          UnitTest::RunAllTests();
      #endif
      
      	int count = 1;
      	while( true )
      	{
      		int row = 0, col = 0;
      		std::cin >> row >> col;
      
      		if( row == col && row == 0 )
      		{
      			break;
      		}
      		
      		int tmp = row;
      		row = col;
      		col = tmp;
      
      		Array arr;
      		createMap( row, col, arr );
      
      		for(int y = 0 ; y < col ; y++)
      		{
      			std::string buf;
      			std::cin >> buf;
      			
      			for(int x = 0 ; x < row ; x++)
      			{
      				if( buf[x] == '*' )
      				{
      					addMine(x, y, arr);
      				}
      			}
      		}
      		
      		std::cout << "Field #" << count << ":" << std::endl;
      		for(int y = 0 ; y < col ; y++)
      		{
      			for(int x = 0 ; x < row ; x++ )
      			{
      				if( arr[y][x] == -1 )
      					std::cout << '*';
      				else
      					std::cout << arr[y][x];
      			}
      			std::cout << std::endl;
      		}
      		std::cout << std::endl;
      
      		count++;
      	}
      
      	return 0;
      }
      #ifdef _UNIT_TEST_
      TEST( testCreationArray )
      {
      	Array arr;
      	createMap( 1, 2, arr );
      
      	CHECK_EQUAL( 2, arr.size() );
      	CHECK_EQUAL( 1, arr[0].size() );
      	CHECK_EQUAL( 0, arr[1][0] );
      }
      
      TEST( testAddSingleMine )
      {
      	Array arr;
      	createMap( 3, 3, arr );
      	addMine( 1,1,arr );
      
      	CHECK_EQUAL( MINE, arr[1][1] );
      	CHECK_EQUAL( 1, arr[0][0] );
      	CHECK_EQUAL( 1, arr[2][2] );
      }
      
      TEST( testAddSingleMineToBoundary )
      {
      	Array arr;
      	createMap( 3, 3, arr );
      	addMine( 2,2,arr );
      
      	CHECK_EQUAL( 1, arr[1][1] );
      	CHECK_EQUAL( MINE, arr[2][2] );
      	CHECK_EQUAL( 1, arr[2][1] );
      }
      
      TEST( testAddSingleMineToBoundary2 )
      {
      	Array arr;
      	createMap( 3, 3, arr );
      	addMine( 0,0,arr );
      
      	CHECK_EQUAL( 1, arr[1][1] );
      	CHECK_EQUAL( MINE, arr[0][0] );
      	CHECK_EQUAL( 1, arr[1][0] );
      }
      
      TEST( testAddMultiMine )
      {
      	Array arr;
      	createMap( 5, 10, arr );
      	addMine( 1,1, arr );
      	CHECK_EQUAL( MINE, arr[1][1] );
      	CHECK_EQUAL( 1,arr[0][0] );
      	CHECK_EQUAL( 1,arr[2][2] ); 
      
      	addMine( 2,2,arr );
      	CHECK_EQUAL( MINE, arr[1][1] );
      	CHECK_EQUAL( MINE,  arr[2][2]);
      	CHECK_EQUAL( 2,arr[1][2]  );
      
      	addMine( 2,2,arr );
      	CHECK_EQUAL(  2, arr[1][2]);
      
      	addMine( 4,9,arr );
      	CHECK_EQUAL( 2, arr[1][2] );
      }
      #endif
      
      /* @END_OF_SOURCE_CODE */
    

ParkPD

  • 졸려서 여기까지만...

      /* @JUDGE_ID:parkpd 10189 C "test" */
      
      /* @BEGIN_OF_SOURCE_CODE */
      
      #include <iostream>
      
      using namespace std;
      
      template<int Width, int Height>
      class CMineBoard
      {
      public:
      	int GetWidth() const { return Width; }
      	int GetHeight() const { return Height; }
      
      	void SetData(int data[])
      	{
      		for (int r = 0; r < Height; ++r)
      		{
      			for (int c = 0; c < Width; ++c)
      			{
      				const int index = r * Width + c;
      				m_Data[r][c] = data[index];
      			}
      		}
      	}
      
      	void GetResult(int data[])
      	{
      		for (int r = 0; r < Height; ++r)
      		{
      			for (int c = 0; c < Width; ++c)
      			{
      				const int index = r * Width + c;
      				data[index] = m_Data[r][c];
      			}
      		}
      	}
      
      	void FindMine()
      	{
      		for (int r = 0; r < Height; ++r)
      		{
      			for (int c = 0; c < Width; ++c)
      			{
      				if (-1 == m_Data[r][c])
      				{
      					FindMine(r, c);
      				}
      			}
      		}
      	}
      
      	void FindMine(int row, int col)
      	{
      		int rFrom = 0;
      		int rTo = 0;
      		int cFrom = 0;
      		int cTo = 0;
      		GetValidRange(row, col, rFrom, rTo, cFrom, cTo);
      
      		for (int r = rFrom; r <= rTo; ++r)
      		{
      			for (int c = cFrom; c <= cTo; ++c)
      			{
      				if (-1 != m_Data[r][c])
      				{
      					m_Data[r][c]++;
      				}
      			}
      		}
      	}
      
      	void GetValidRange(int r, int c, int& rFrom, int& rTo, int& cFrom, int& cTo) const
      	{
      		rFrom = std::max(r - 1, 0);
      		rTo = std::min(r + 1, Height - 1);
      		cFrom = std::max(c - 1, 0);
      		cTo = std::min(c + 1, Width - 1);
      	}
      
      	int m_Data[Height][Width];
      };
      
      #define _UNIT_TEST
      
      #ifndef _UNIT_TEST
      
      int main()
      {
      	return 0;
      }
      
      #else
      
      #include "../../UnitTest++/src/UnitTest++.h"
      
      typedef CMineBoard<3, 4> CMainBoard34;
      typedef CMineBoard<4, 4> CMainBoard44;
      
      TEST(GetWidth)
      {
      	CMainBoard34 board;
      	CHECK_EQUAL(3, board.GetWidth());
      	CHECK_EQUAL(4, board.GetHeight());
      }
      
      TEST(SetData)
      {
      	CMainBoard44 board;
      	CHECK_EQUAL(4, board.GetWidth());
      	CHECK_EQUAL(4, board.GetHeight());
      
      	int data[16] = {-1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0};
      	board.SetData(data);
      	CHECK_EQUAL(-1, board.m_Data[0][0]);
      	CHECK_EQUAL(0, board.m_Data[0][1]);
      }
      
      struct FixtureBoard
      {
      	FixtureBoard()
      	{
      		rFrom = 0;
      		rTo = 0;
      		cFrom = 0;
      		cTo = 0;
      	}
      
      	int rFrom;
      	int rTo;
      	int cFrom;
      	int cTo;
      };
      
      struct Fixture4 : public FixtureBoard
      {
      	Fixture4()
      	{
      		int data[16] = {-1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0};
      		board.SetData(data);
      	}
      
      	CMainBoard44 board;
      };
      
      TEST_FIXTURE(Fixture4, GetValidRange)
      {
      	board.GetValidRange(0, 0, rFrom, rTo, cFrom, cTo);
      	CHECK_EQUAL(0, rFrom);
      	CHECK_EQUAL(1, rTo);
      	CHECK_EQUAL(0, cFrom);
      	CHECK_EQUAL(1, cTo);
      
      	board.GetValidRange(1, 1, rFrom, rTo, cFrom, cTo);
      	CHECK_EQUAL(0, rFrom);
      	CHECK_EQUAL(2, rTo);
      	CHECK_EQUAL(0, cFrom);
      	CHECK_EQUAL(2, cTo);
      
      	board.GetValidRange(3, 3, rFrom, rTo, cFrom, cTo);
      	CHECK_EQUAL(2, rFrom);
      	CHECK_EQUAL(3, rTo);
      	CHECK_EQUAL(2, cFrom);
      	CHECK_EQUAL(3, cTo);
      }
      
      TEST_FIXTURE(Fixture4, FindMineAndGetResult)
      {
      	board.FindMine();
      
      	int expect[16] = 
      	{
      		-1,  1, 0, 0, 
      		 2,  2, 1, 0, 
      		 1, -1, 1, 0, 
      		 1,  1, 1, 0
      	};
      
      	int result[16];
      	board.GetResult(result);
      	CHECK_ARRAY_EQUAL(expect, result, 16);
      }
      
      struct Fixture53 : public FixtureBoard
      {
      	typedef CMineBoard<5, 3> CMainBoard53;
      	CMainBoard53 board;
      };
      
      TEST_FIXTURE(Fixture53, FindMineAndGetResult1)
      {
      	board.GetValidRange(2, 1, rFrom, rTo, cFrom, cTo);
      	CHECK_EQUAL(1, rFrom);
      	CHECK_EQUAL(2, rTo);
      	CHECK_EQUAL(0, cFrom);
      	CHECK_EQUAL(2, cTo);
      
      	int data1[15] = {
      		-1, -1, 0, 0, 0, 
      		 0,  0, 0, 0, 0, 
      		 0, -1, 0, 0, 0
      	};
      	board.SetData(data1);
      	board.FindMine();
      
      	int expect[15] = 
      	{
      		-1, -1, 1, 0, 0, 
      		 3,  3, 2, 0, 0, 
      		 1, -1, 1, 0, 0
      	};
      
      	int result[15];
      	board.GetResult(result);
      	CHECK_ARRAY_EQUAL(expect, result, 15);
      }
      
      int main()
      {
      	UnitTest::RunAllTests();
      
      	char temp;
      	cin >> temp;
      
      	return 0;
      }
      
      #endif
      
      /* @END_OF_SOURCE_CODE */
    

MovingSpotlight

1차 풀이

  • 코드가 꽤 지저분합니다만 일단...

  • 결과적으로 wrong answer입니다.

         1. #include <iostream>
            #include <cassert>
            #include <vector>
      
            using namespace std;
      
            struct FieldSection
            {
                int      row;        // height
                int      col;        // width
      
                char    *pBufIn;
                char    *pBufOut;
      
                int      fieldNum;
            };
      
            void ComputeMinePos(vector<FieldSection> &vField)
            {
                assert(vField.size() > 0);
      
                int width, height, mineCount;
      
                for(int i = 0; i < vField.size(); i++)
                {
                    width        = vField[i].col;
                    height       = vField[i].row;       
                    mineCount    = 0;
      
                    for(int h = 0; h < height; h++)
                    {
                        for(int w = 0; w < width; w++)
                        {
                            if(vField[i].pBufIn[h * width + w] == '*')
                            {
                                vField[i].pBufOut[h * width + w] = '*';
                            }
                            else
                            {
                                for(int maskH = h - 1; maskH <= h + 1; maskH++)
                                {
                                    for(int maskW = w - 1; maskW <= w + 1; maskW++)
                                    {
                                        if(maskH < 0 || maskW < 0 || maskH > height-1 || maskW > width-1)
                                            continue;
      
                                        if(vField[i].pBufIn[(maskH * width + maskW)] == '*')
                                            mineCount++;                           
                                    }
                                }
                                vField[i].pBufOut[h * width + w] = mineCount;
                                mineCount = 0;
                            }               
                        }
                    }
      
                }
            }
            void PrintResult(vector<FieldSection> &vField)
            {
                assert(vField.size() > 0);
      
                for(int i = 0; i < vField.size(); i++)
                {
                    cout << "Field #" << vField[i].fieldNum << endl;
      
                    int width = vField[i].col;
      
                    for(int row = 0; row < vField[i].row; row++)
                    {
                        for(int col = 0; col < vField[i].col; col++)
                        {
                            if(vField[i].pBufOut[row * width + col] == '*')
                                cout << vField[i].pBufOut[row * width + col];
                            else
                                cout << (int)(vField[i].pBufOut[row * width + col]);
                        }
      
                        cout << endl;
                    }
                }
            }
      
            int main()
            {
                int      row, col;
                int      count    = 1;
                char    *pIn    = 0;
                char    *pOut    = 0;
      
                const int MAX_BUF = 100;
                char    buf[MAX_BUF] = {0, };
      
                vector<FieldSection>    vField;
      
                while(1)
                {
                    cin >> row >> col;
      
                    //if(row == 0 || col == 0)
                    //    continue;
      
                    if(row == 0 && col == 0)
                    {
                        break;
                    }
                    else
                    {
                        pIn     = new char[sizeof(char) * row * col + 1];
                        pOut    = new char[sizeof(char) * row * col + 1];
      
                        memset(pIn, 0x00, sizeof(char) * row * col + 1);
                        memset(pOut, 0x00, sizeof(char) * row * col + 1);
                       
                        for(int i = 0; i < row; i++)
                        {
                            cin >> buf;
                            assert(strlen(buf) == col);
      
                            strcat(pIn, buf);
                            buf[0] = 0;
                        }
      
                        FieldSection myField;
                        myField.row         = row;
                        myField.col         = col;
                        myField.pBufIn      = pIn;
                        myField.pBufOut     = pOut;
                        myField.fieldNum    = count;
      
                        vField.push_back(myField);
                       
                        pIn   = 0;
                        pOut  = 0;
                        count++;
                    }
                }
      
                ComputeMinePos(vField);
                PrintResult(vField);
      
                for(int i = 0; i < vField.size(); i++)
                {
                    delete[] vField[i].pBufIn;
                    delete[] vField[i].pBufOut;
                }
      
                return 0;
            }
    

폭풍언덕

  • 유닛테스트 경험이 없어서 테스트 코드는 포함하지 않았습니다.

  • MineSweeper.java

      import java.util.*;
      import java.io.*;
      
      public class MineSweeper 
      {
      	static Vector<Matrix> matrixVec;
      	
      	public static void main(String[] args) throws IOException
      	{
      		matrixVec = new Vector<Matrix>();
      		
      		// 입력이 (0,0)일때가지 반복한다.
      		while (true)
      		{		
      			// (row, col)을 읽는다.
      			BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
      		
      			String line = in.readLine();
      			StringTokenizer tokens = new StringTokenizer(line, " ");
      		
      			// 오류 체크
      			if (tokens.countTokens() != 2)
      			{
      				System.out.println("Error : Invalid Matrix Size!!");
      				return;
      			}
      		
      			int row = Integer.parseInt(tokens.nextToken());
      			int col = Integer.parseInt(tokens.nextToken());
      			
      			// (0, 0) 이면 결과를 출력하고 종료한다.
      			if (row == 0 && col == 0)   // if close then print results
      			{
      				showMatrixVec();
      				return;
      			}
      			
      			// matrix 생성
      			Matrix matrix = new Matrix(row, col);
      		
      		
      			// 입력을 읽어 matrix에 저장한다.
      			for (int i=0; i<row; i++)
      			{
      				BufferedReader rowIn = new BufferedReader(new InputStreamReader(System.in));
      				String rowLine = rowIn.readLine();
      			
      				// 입력 데이터 오류 체크
      				if (rowLine.length() != col)
      				{
      					System.out.println("Error: Invalid Input Data!!");
      					return;
      				}
      			
      				for (int j=0; j<col; j++)
      				{
      					matrix.setValue(i, j, rowLine.charAt(j));
      				}
      			}
      		
      			// 매트릭스를 읽어 지뢰를 발견하면 카운트를 계산한다.
      			for (int i=0; i<row; i++)
      			{
      				for (int j=0; j<col; j++)
      				{
      					if (matrix.findMine(i,j))
      						matrix.addMineCount(i, j);
      				}
      			}
      			
      			// 매트릭스를 저장한다.
      			matrixVec.add(matrix);
      		}
      
      	}
      	
      	// 매트릭스를 출력한다.
      	public static void showMatrixVec()
      	{
      		for (int i=0; i<matrixVec.size(); i++)
      		{
      			Matrix mat = matrixVec.elementAt(i);
      			mat.show();
      		}	
      	}
      }
    
  • Matrix.java

      public class Matrix {
      	private int row;
      	private int col;
      	
      	private char[][] mat;		// 입력 데이터를 저장하기 위한 배열
      	private int[][] val;		// 출력 데이터를 저장하기 위한 배열
      
      	
      	// 배열을 생성하고 0으로 초기화한다.
      	Matrix(int _row, int _col)
      	{
      		row = _row;
      		col = _col;
      		
      		mat = new char[row][col];
      		val = new int[row][col];
      		
      		for (int i=0; i<row; i++)
      		{
      			for (int j=0; j<col; j++)
      			{
      				mat[i][j] = '.';
      				val[i][j] = 0;
      			}
      		}
      	}
      	
      	void setValue(int _row, int _col, char value)
      	{
      		mat[_row][_col] = value;
      	}
      	
      	boolean findMine(int _row, int _col)
      	{
      		if (mat[_row][_col] == '*')
      			return true;
      		
      		return false;
      	}
      	
      	// 지뢰 주위의 셀들을 찾아서 카운트를 1씩 증가시킨다.
      	void addMineCount(int _row, int _col)
      	{
      		for (int i=-1; i<2; i++)
      		{
      			for (int j=-1; j<2; j++)
      			{
      				int x = _row + i;
      				int y = _col + j;
      				
      				if (isValid(x, y) && val[x][y] != -1)
      					val[x][y]++;			
      			}
      		}
      		val[_row][_col] = -1;
      	}
      	
      	// 셀의 범위가 메트릭스 안에 있는지 체크한다.
      	boolean isValid(int x, int y)
      	{
      		if ((x>= 0 && x<row) && (y>=0 && y<col))
      			return true;
      		
      		return false;
      	}
      	
      	// 매트릭스를 출력한다.
      	void show()
      	{
      		for (int i=0; i<row; i++)
      		{
      			for (int j=0; j<col; j++)
      			{
      				if (val[i][j] == -1)
      					System.out.print("*");
      				else
      					System.out.print(val[i][j]);
      			}
      			System.out.println();
      		}
      	}
      }
    

jeddi

    #include <memory.h>
    #include <iostream>
    #include <list>
    
    const int MINE_CONSTANT = 10000;
    
    
    //struct POINT
    //{
    //	int x;
    //	int y;
    //};
    const char searchMatrix[][2] = { {-1, -1}, { 0, -1 }, { 1, -1 }, 
    								 {-1,  0},            { 1,  0 }, 
    								 {-1,  1}, { 0,  1 }, { 1,  1 } };
    
    
    class CGameMatrix
    {
    public:
    	CGameMatrix()
    	{
    		m_Row = 0;
    		m_Column = 0;
    
    		m_Matrix = NULL;
    	};
    
    	~CGameMatrix()
    	{
    		if( m_Matrix )
    		{
    			for( int i = 0; i < m_Row; i++ )
    			{
    				if( m_Matrix[i] != NULL )
    					delete m_Matrix[i];			
    			}
    
    			delete m_Matrix;
    		}		
    	};
    
    
    	void Init( int row, int column )
    	{ 
    		m_Column	= column;
    		m_Row		= row;
    
    		m_Matrix = new int*[row];
    		for( int i = 0; i < row; i++ )
    		{
    			m_Matrix[i] = new int[column];
    			memset( m_Matrix[i], 0, sizeof(m_Matrix[i])*column );
    		}
    	}
    
    	void	SetMine( int row, int column )
    	{
    		m_Matrix[row][column] = MINE_CONSTANT;
    	}
    
    	int		GetMineCount( int row, int column )
    	{
    		return m_Matrix[row][column];
    	}
    
    
    	/// 하나의 위치값 계산
    	/// 1.내가 주위에 지뢰가 있는 검사하는 능동적 방벙..
    	int		GetAdjacentMineCount( int row, int column )
    	{
    		int mineCount = 0;
    		int searchCount = sizeof(searchMatrix) / sizeof(searchMatrix[0]);
    		for( int i = 0; i < searchCount; i++ )
    		{
    			int tc = column + searchMatrix[i][0];
    			int tr = row + searchMatrix[i][1];
    
    			if( IsValidPosition( tr, tc ) )
    			{
    				if( m_Matrix[tr][tc] == MINE_CONSTANT )
    					mineCount++;
    			}
    		}
    
    		return mineCount;
    	}
    
    	/// 2. 지뢰가 주변의 위치에 자신의 존재를 알리는 수동적 방법
    	void	IncreaseMineCount( int row, int column )
    	{
    		int mineCount = 0;
    		int searchCount = sizeof(searchMatrix) / sizeof(searchMatrix[0]);
    		for( int i = 0; i < searchCount; i++ )
    		{
    			int tc = column + searchMatrix[i][0];
    			int tr = row + searchMatrix[i][1];
    
    			if( IsValidPosition( tr, tc ) )
    			{
    				if( m_Matrix[tr][tc] != MINE_CONSTANT )
    					m_Matrix[tr][tc]++;
    			}
    		}
    	}
    
    
    
    	/// 전체 계산
    	void	ComputeAdjacentMineCount()
    	{		
    		for( int i =0; i < m_Row; i++)
    		{
    			for( int j = 0; j < m_Column; j++ )
    			{
    				if( GetMineCount(i,j) == MINE_CONSTANT )
    					IncreaseMineCount(i,j);
    					//continue;
    
    				//int count = GetAdjacentMineCount( i, j );
    				//m_Matrix[i][j] = count;
    			}
    		}
    	}
    
    	/// 출력
    	void PrintOutput()
    	{	
    		for( int i = 0; i < m_Row; i++ )
    		{
    			for( int j = 0; j < m_Column; j++ )
    			{
    				int mineCount = GetMineCount(i, j);
    				if( mineCount == MINE_CONSTANT )
    					std::cout << '*';
    				else
    					std::cout << mineCount;				
    			}
    
    			std::cout << std::endl;
    		}	
    	}
    
    
    private:
    	bool	IsValidPosition( int row, int column )
    	{
    		if( column < 0 || row < 0 )
    			return false;
    
    		if( column >= m_Column || row >= m_Row )
    			return false;
    
    		return true;
    	}
    
    	
    
    private:
    	
    
    	int		m_Column;
    	int		m_Row;
    
    	int**	m_Matrix;	
    };
    
    
    
    int main()
    {
    	int column, row;
    		
    	int fieldNO = 1;
    	while( std::cin >> row >> column )
    	{	
    		if( row == 0 || column == 0 )
    			break;
    
    		CGameMatrix* pMatrix = new CGameMatrix();
    		pMatrix->Init( row, column );
    
    		/// input
    		for( int i = 0; i < row; i++ )
    		{
    			for( int j = 0; j < column; j++ )
    			{
    				char input;
    				std::cin >> input;
    				if( input == '*' )
    					pMatrix->SetMine( i, j );
    			}
    		}		
    
    		pMatrix->ComputeAdjacentMineCount();		
    
    		if( fieldNO > 1 )
    			std::cout << std::endl;
    		std::cout << "Field #" << fieldNO << ":" << std::endl;
    		pMatrix->PrintOutput();
    		fieldNO++;				
    		//std::cout << std::endl;
    	}
    
    	return 0;
    }

CynicJJ

!ModuleMain.vb

    ' Programming Challenges
    ' 2번 문제. 지뢰찾기
    ' 사용자로부터 지뢰 데이터 입력받아 주변의 지뢰 갯수 계산 후 출력
    Module ModuleMain
    
    	Sub Main()
    		' 컨트롤러와 보드 준비
    		Dim aBoard As New Board
    		Dim aControler As New Controler
    		aControler.SetBoard(aBoard)
    
    		' 입력 받기
    		While True
    			' 지뢰밭 크기 입력 받기
    			Dim inputStr As String = Console.ReadLine()
    			Dim boardSize As System.Drawing.Size = aControler.GetBoardSize(inputStr)
    			Dim rows As Integer = boardSize.Height
    			Dim columns As Integer = boardSize.Width
    			' 크기가 0 0 이면 종료
    			If rows = 0 And columns = 0 Then Exit While
    			' 지뢰 데이터 입력 받기
    			Dim mineData(rows - 1) As String
    			For i As Integer = 0 To mineData.GetUpperBound(0)
    				mineData(i) = Console.ReadLine()	' 한줄씩 입력 받음
    			Next
    			' 입력 받은 지뢰 데이터 이용 보드 설정
    			aControler.SetupBoardFromMineData(mineData)
    			' 출력
    			PrintBoard(aBoard, rows, columns)
    			' 보드 초기화
    			aBoard.Clear()
    		End While
    	End Sub
    
    	' 지뢰판 출력
    	Private Sub PrintBoard(ByVal aBoard As Board, ByVal rows As Integer, ByVal columns As Integer)
    		For row As Integer = 1 To rows
    			For column As Integer = 1 To columns
    				If aBoard.GetCell(row, column).IsMine Then
    					Console.Write("*")	' 지뢰면 * 출력
    				Else
    					Console.Write("{0:D}", aBoard.GetMineCountAt(row, column))	' 지뢰 아니면 주위 지뢰 갯수 출력
    				End If
    			Next
    			Console.WriteLine()
    		Next
    	End Sub
    
    End Module

Board.vb

    ' 지뢰밭
    Public Class Board
    
    	' 셀들은 위치값을 키로 가지는 해시맵에 저장
    	Private _cells As New Dictionary(Of String, Cell)
    
    	' 특정 위치 Cell 주위의 지뢰 갯수
    	Public Function GetMineCountAt(ByVal row As Integer, ByVal column As Integer) As Integer
    		Return GetMineCount(GetNearCellsAt(row, column))
    	End Function
    
    	' 셀 추가
    	Public Sub AddCell(ByVal cell As Cell, ByVal row As Integer, ByVal column As Integer)
    		If cell IsNot Nothing Then
    			_cells.Add(GetHashKey(row, column), cell)
    		End If
    	End Sub
    
    	' 셀 가져오기
    	Public Function GetCell(ByVal row, ByVal column) As Cell
    		Dim key As String = GetHashKey(row, column)
    		If _cells.ContainsKey(key) Then
    			Return _cells.Item(key)
    		Else
    			Return Nothing
    		End If
    	End Function
    
    	' 위치로부터 문자열 키 가져오기
    	Public Function GetHashKey(ByVal row, ByVal column) As String
    		Return String.Format("{0:D},{1:D}", row, column)
    	End Function
    
    	' 특정 위치 셀의 주변 셀들 8개 가져오기
    	Public Function GetNearCellsAt(ByVal row As Integer, ByVal column As Integer) As ArrayList
    		Dim cells As New ArrayList()
    
    		Dim aCell As Cell
    		aCell = GetCell(row - 1, column - 1)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row - 1, column)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row - 1, column + 1)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row, column - 1)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row, column + 1)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row + 1, column - 1)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row + 1, column)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    		aCell = GetCell(row + 1, column + 1)
    		If aCell IsNot Nothing Then cells.Add(aCell)
    
    		Return cells
    	End Function
    
    	' 여러 셀들 중 지뢰인것 갯수 세기
    	Public Function GetMineCount(ByVal cells As ArrayList) As Integer
    		Dim mineCount As Integer
    		For Each cell As Cell In cells
    			If cell.IsMine Then
    				mineCount += 1
    			End If
    		Next
    
    		Return mineCount
    	End Function
    
    	' 지뢰밭 초기화
    	Public Sub Clear()
    		_cells.Clear()
    	End Sub
    End Class

Cell.vb

    ' 지뢰밭의 각 셀
    Public Class Cell
    
    	Private _isMine As Boolean
    
    	Sub New(Optional ByVal isMine As Boolean = False)
    		_isMine = isMine
    	End Sub
    
    	Public ReadOnly Property IsMine() As Boolean
    		Get
    			Return _isMine
    		End Get
    	End Property
    
    End Class

Controler.vb

    ' 사용자 입력을 분석하고 지뢰밭 설정
    Public Class Controler
    
    	Private _board As Board		' 지뢰밭
    
    	Public Sub SetBoard(ByVal aBoard As Board)
    		_board = aBoard
    	End Sub
    
    	' 사용자 입력으로 부터 지뢰밭 크기 가져오기
    	Public Function GetBoardSize(ByVal inputStr As String) As System.Drawing.Size
    		' 문자열을 공백기준으로 분리
    		Dim separator As Char() = {" "}
    		Dim inputs As String() = inputStr.Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries)
    		' 보드 크기 설정
    		Dim size As New System.Drawing.Size
    		size.Height = Integer.Parse(inputs(0).Trim())
    		size.Width = Integer.Parse(inputs(1).Trim())
    
    		Return size
    	End Function
    
    	' 사용자가 입력한 지뢰 데이터로 지뢰밭 설정
    	Public Sub SetupBoardFromMineData(ByVal mineData As String())
    		For i As Integer = 0 To mineData.GetUpperBound(0)
    			AddCellsByMineData(mineData(i), i + 1)	' 주의 row = i+1
    		Next
    	End Sub
    
    	' 지뢰 데이터로부터 지뢰밭에 지뢰 추가
    	' * 이면 지뢰 . 이면 지뢰 아님
    	Public Sub AddCellsByMineData(ByVal data As String, ByVal row As Integer)
    		Dim mark As Char() = data.ToCharArray()
    		For i As Integer = 0 To mark.GetUpperBound(0)
    			If mark(i).Equals("."c) Then
    				_board.AddCell(New Cell(), row, i + 1)	' 주의 row = i+1
    			ElseIf mark(i).Equals("*"c) Then
    				_board.AddCell(New Cell(True), row, i + 1)	' 주의 row = i+1
    			End If
    		Next
    	End Sub
    End Class

Clone this wiki locally