마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

이 상태에서 꼭 2차원 배열을 써야될때... 수정해봤는데 좀 봐주실수있나요 ? ㅠㅠ

0 추천
package com.example.theater;

import ...

public class MainActivity extends AppCompatActivity {

    EditText row,col;
    Button btn1;
    TextView textResult;
    int i,j,pax;
    private Button[][] board = new Button[5][5];

    private int[][]boardId={{R.id.seat11, R.id.seat12, R.id.seat13, R.id.seat14, R.id.seat15},
            {R.id.seat21, R.id.seat22, R.id.seat23, R.id.seat24, R.id.seat25},
            {R.id.seat31, R.id.seat32, R.id.seat33, R.id.seat34, R.id.seat35},
            {R.id.seat41, R.id.seat42, R.id.seat43, R.id.seat44, R.id.seat45},
            {R.id.seat51, R.id.seat52, R.id.seat53, R.id.seat54, R.id.seat55}};


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        row = findViewById(R.id.row);
        col = findViewById(R.id.col);
        btn1 = findViewById(R.id.btn1);
        textResult = findViewById(R.id.textResult);
        i = Integer.parseInt(row.getText().toString());
        j = Integer.parseInt(col.getText().toString());
        pax=25;

           for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    this.board[i][j] = (Button)findViewById(boardId[i][j]);
                }
            }
            btn1.setOnClickListener(v -> {

                while (pax > 0) {
                    if ((j > 5 || j < 1) || (i > 5 || i < 1)) {
                        Toast.makeText(getApplicationContext(), "잘못된 입력입니다. 다시 입력하세요.", Toast.LENGTH_LONG).show();
                        continue;
                    }

                    if (boardId[j - 1][i - 1] == 0) {
                        board[i][j].setBackgroundColor(Color.parseColor("#FF0000"));
                        boardId[j - 1][i - 1] = 1;
                    } else {
                        Toast.makeText(getApplicationContext(), "예약이 완료된 자리입니다. 다시 예약하세요.", Toast.LENGTH_LONG).show();
                    }
                }
            }
            );
        }}

 

이렇게 바꿔봤는데.... 앱 구동이 안되네요ㅠㅠ 이상한 쪽으로 수정했을까여???

비니온 (210 포인트) 님이 2022년 8월 21일 질문

2개의 답변

0 추천
 
채택된 답변

에러는 로그를 확인하시면서 차근차근해결 하시구요. 몇가지 눈에 띄는 것만 짚어볼게요.

private EditText row, col;
private Button btn1;
private TextView textResult;

위의 멤버변수들은 외부에 공개할 필요가 없으므로 private으로 만들어 주세요.

 

btn1.setOnClickListener(v -> {
            int i = Integer.parseInt(row.getText().toString());
            int j = Integer.parseInt(col.getText().toString());

            ...
        });

멤버변수인 i, j는 불필요한 멤버이므로 제거하시고, 대신 btn1의 클릭이벤트 안으로 코드를 옮기세요,

 

@Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        btn1.setOnClickListener(v -> seatClicked() );
    }

    private void seatClicked() {
        int colNo = Integer.parseInt(col.getText().toString());
        int rowNo = Integer.parseInt(row.getText().toString());

        while (pax > 0) {
            if ((colNo > 5 || colNo < 1) || (rowNo > 5 || rowNo < 1)) {
                Toast.makeText(getApplicationContext(), "잘못된 입력입니다. 다시 입력하세요.", Toast.LENGTH_LONG).show();
                continue;
            }

            if (boardId[colNo - 1][rowNo - 1] == 0) {
                board[rowNo][colNo].setBackgroundColor(Color.parseColor("#FF0000"));
                boardId[colNo - 1][rowNo - 1] = 1;
            } else {
                Toast.makeText(getApplicationContext(), "예약이 완료된 자리입니다. 다시 예약하세요.", Toast.LENGTH_LONG).show();
            }
        }
    }

btn1의 클릭이벤트 안의 코드를 빼내서 별도의 메소드로 만드세요. 그래야 읽기에 더 좋습니다. 그리고 i, j도 알기쉬운 변수명으로 바꾸세요.

 

    private Integer getColNo() {
        return EditableToInteger(col.getText());
    }

    private Integer getRowNo() {
        return EditableToInteger(row.getText());
    }

    private Integer EditableToInteger(Editable editable) {
        try {
            return Integer.parseInt(editable.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }

열과 행 입력 값을 텍스트에서 정수로 변환하는 부분을 추가하세요. 예외처리도 하시구요.

 

private void seatClicked() {
        Integer colNo = getColNo();
        Integer rowNo = getRowNo();

        if (colNo == null || rowNo == null) {
            Toast.makeText(getApplicationContext(), "잘못된 입력입니다. 다시 입력하세요.", Toast.LENGTH_LONG).show();
            return;
        }

        ...
    }

seatClicked 메소드 안에 유효성 검사코드를 집어넣으세요.

if ((colNo > 5 || colNo < 1) || (rowNo > 5 || rowNo < 1)) {
            Toast.makeText(getApplicationContext(), "잘못된 입력입니다. 다시 입력하세요.", Toast.LENGTH_LONG).show();
            return;
        }


while (pax > 0) {
 . ..
}

행과 열 범위 체크하는 코드는 while문 밖으로 빼네세요.

 

while (pax > 0) {
            if (boardId[colNo - 1][rowNo - 1] == 0) {
                board[rowNo][colNo].setBackgroundColor(Color.parseColor("#FF0000"));
                boardId[colNo - 1][rowNo - 1] = 1;
            } else {
                Toast.makeText(getApplicationContext(), "예약이 완료된 자리입니다. 다시 예약하세요.", Toast.LENGTH_LONG).show();
            }
        }

위의 코드는 동작하지 않는 코드입니다. 먼저 pax가 뭔지 모르겠고, 왜 pax - 25으로 고정인데, 변수로 사용하고 있고 while (pax > 0) 은 뭐를 하는지 모르겠네요. 무한루프처럼 보이는데 말이죠. 그리고 이미 예약이 되어 있는지 아닌지는 예약여부 상태를 저장할 수 있도록 구조가 변경되어야 합니다. 이 부분은 약간의 고민이 필요해 보입니다.

 

private void seatClicked() {
        ...

        bookSeat(colNo, rowNo);
    }

    private void bookSeat(Integer colNo, Integer rowNo) {
     

    }

우선은 부킹을 처리하는 부분의 코드를 밖으로 빼네서 읽기 좋게 만들어 놓겠습니다.

spark (228,010 포인트) 님이 2022년 8월 21일 답변
비니온님이 2022년 8월 23일 채택됨
0 추천

bookSeat메소드는 가장 간단하게는 View.tag 속성을 이용하여 아래처럼 처리할 수는 있습니다.

private void bookSeat(Integer colNo, Integer rowNo) {
        Button seat = Objects.requireNonNull(board[colNo - 1][rowNo - 1]);

        Object bookedStatusValue = seat.getTag(R.string.booked_status_key);
        Boolean isBooked = bookedStatusValue == null ? Boolean.FALSE : (Boolean) bookedStatusValue;
        if (isBooked) {
            Toast.makeText(getApplicationContext(), "예약이 완료된 자리입니다. 다시 예약하세요.", Toast.LENGTH_LONG).show();
            return;
        }

        seat.setBackgroundColor(Color.parseColor("#FF0000"));
        seat.setTag(R.string.booked_status_key, Boolean.TRUE);
    }

하지만 이 방법은 상태의 관리를 위해 불필요하게 뷰를 건드리기 때문에 코드의 관점에서는 좋은 않은 코드입니다. 이런 코드는 데이터를 저장거나 단위테스트 하기에 좋지 않고, 유지보수 할 때도 금방 엉망이 되기 쉬운 bad practice에 해당하는 코드입니다. Seat와 Board라는 클래스를 만들고 예약상태를 좌석에 따라 관리하고 이걸 기반으로 뷰만 업데이트 방식이 더 좋은 코드입니다.

데이터를 중심으로 해서 뷰를 단지 데이터를 화면에 보여주는 멍청한 뷰(더 좋은 코드임)로 만드는 에제롤 적어봅니다. 제 코드가 최선은 아닙니다. 다만 개념을 보여주는 용도이므로 참고만 하시고 제가 말씀드리는 포인트를 이해하시고 코드를 작성하시기 바랍니다.

public class Seat {
    private final int id;
    private final String label;
    private boolean booked;
    private int xPos;
    private int yPos;

    public Seat(int id, String label, int xPos, int yPos) {
        this.id = id;
        this.label = label;
        this.xPos = xPos;
        this.yPos = yPos;
    }

    public int getId() {
        return id;
    }

    public String getLabel() {
        return label;
    }

    public boolean isBooked() {
        return booked;
    }

    public void setBooked(boolean booked) {
        this.booked = booked;
    }

    public int getxPos() {
        return xPos;
    }

    public void setxPos(int xPos) {
        this.xPos = xPos;
    }

    public int getyPos() {
        return yPos;
    }

    public void setyPos(int yPos) {
        this.yPos = yPos;
    }

    @Override
    public String toString() {
        return "Seat{" +
                "id=" + id +
                ", label='" + label + '\'' +
                ", booked=" + booked +
                ", xPos=" + xPos +
                ", yPos=" + yPos +
                '}';
    }
}

 

import java.util.Objects;

public class Board {
    private Seat[][] seats;

    public void createSeats(int[][] boardIds) {
        int colCount = boardIds.length;
        int rowCount = boardIds[0].length;
        seats = new Seat[colCount][rowCount];
        for (int i = 0; i < colCount; i++) {
            for (int j = 0; j < rowCount; j++) {
                int seatId = boardIds[i][j];
                String label = "" + ((i % rowCount) * rowCount + j + 1);
                seats[i][j] = new Seat(seatId, label, i, j);
            }
        }
    }

    public Seat[][] getSeats() {
        return seats;
    }

    public BookResult bookSeat(String colText, String rowText) {
        BookResult validationResult = validate(colText, rowText);
        if (!validationResult.isSuccess()) return validationResult;

        Seat seat = validationResult.getSeat();
        seat.setBooked(true);

        return BookResult.success(seat);
    }

    private BookResult validate(String colText, String rowText) {
        Integer colNo = strToInt(colText);
        Integer rowNo = strToInt(rowText);

        if (colNo == null || rowNo == null) {
            return BookResult.error("잘못된 입력입니다. 다시 입력하세요.");
        }

        if ((colNo > 5 || colNo < 1) || (rowNo > 5 || rowNo < 1)) {
            return BookResult.error("잘못된 입력입니다. 다시 입력하세요.");
        }

        Seat seat = Objects.requireNonNull(seats[colNo - 1][rowNo - 1]);
        if (seat.isBooked()) {
            return BookResult.error("예약이 완료된 자리입니다. 다시 예약하세요.");
        }

        return BookResult.success(seat);
    }

    private Integer strToInt(String s) {
        try {
            return Integer.parseInt(s);
        } catch (NumberFormatException e) {
            return null;
        }
    }
}

 

public class BookResult {
    private final boolean success;
    private final String message;
    private Seat seat;

    private BookResult(boolean success, String message, Seat seat) {
        this.success = success;
        this.message = message;
        this.seat = seat;
    }

    public static BookResult success(Seat seat) {
        return new BookResult(true, null, seat);
    }

    public static BookResult error(String message) {
        return new BookResult(false, message, null);
    }

    public boolean isSuccess() {
        return success;
    }

    public String getMessage() {
        return message;
    }

    public Seat getSeat() {
        return seat;
    }
}

 

public class MainActivity extends AppCompatActivity {

    private static final String BOOKED_COLOR = "#FF0000";

    private EditText row, col;
    private Button btn1;
    private TextView textResult;

    //private int pax; //용도를 알 수없어 주석처리
    private Button[][] seatViews = new Button[5][5];

    private static final int[][] boardIds = {{R.id.seat11, R.id.seat12, R.id.seat13, R.id.seat14, R.id.seat15},
            {R.id.seat21, R.id.seat22, R.id.seat23, R.id.seat24, R.id.seat25},
            {R.id.seat31, R.id.seat32, R.id.seat33, R.id.seat34, R.id.seat35},
            {R.id.seat41, R.id.seat42, R.id.seat43, R.id.seat44, R.id.seat45},
            {R.id.seat51, R.id.seat52, R.id.seat53, R.id.seat54, R.id.seat55}};

    private final Board board = new Board();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_acivity);

        row = findViewById(R.id.row);
        col = findViewById(R.id.col);
        btn1 = findViewById(R.id.btn1);
        textResult = findViewById(R.id.textResult);
        //pax = 25;

        for (int i = 0; i < boardIds.length; i++) {
            for (int j = 0; j < boardis[i].length; j++) {
                seatViews[i][j] = findViewById(boardIds[i][j]);
            }
        }

        board.createSeats(boardIds);
        updateSeats();

        btn1.setOnClickListener(v -> bookSeat());
    }

    private void bookSeat() {
        BookResult bookResult = board.bookSeat(col.getText().toString(), row.getText().toString());
        if (!bookResult.isSuccess()) {
            Toast.makeText(this, bookResult.getMessage(), Toast.LENGTH_SHORT).show();
            return;
        }

        updateSeats();
    }

    private void updateSeats() {
        Seat[][] seats = board.getSeats();
        for (Seat[] seat : seats) {
            for (Seat value : seat) {
                Button seatView = seatViews[value.getxPos()][value.getyPos()];
                seatView.setText(value.getLabel());
                if (value.isBooked()) {
                    seatView.setBackgroundColor(Color.parseColor(BOOKED_COLOR));
                }
            }
        }
    }
}

 

spark (228,010 포인트) 님이 2022년 8월 21일 답변
spark님이 2022년 8월 21일 수정
덕분에 많은 도움이 되었습니다. 감사합니다.^^
...