Làm thế nào để có các hoạt động với nhân vật / vật phẩm trong nhị phân với các hoạt động cụ thể?


8

Tôi có vấn đề tiếp theo.

Một mục có thể có rất nhiều trạng thái:

NORMAL  = 0000000
DRY     = 0000001
HOT     = 0000010
BURNING = 0000100
WET     = 0001000
COLD    = 0010000
FROZEN  = 0100000
POISONED= 1000000

Một mục có thể có một số trạng thái cùng một lúc nhưng không phải tất cả chúng

  • Không thể khô và ướt cùng một lúc.
  • Nếu bạn GỌI một mục WET, nó sẽ biến thành FROZEN.
  • Nếu bạn NÓNG một vật phẩm ƯỚT, nó sẽ biến thành BÌNH THƯỜNG
  • Một mục có thể là BURNING và POISON

Vân vân.

Tôi đã cố gắng đặt cờ nhị phân thành các trạng thái và sử dụng AND để kết hợp các trạng thái khác nhau, kiểm tra trước nếu có thể hoặc không thực hiện hoặc thay đổi sang trạng thái khác.

Có tồn tại một cách tiếp cận cụ thể để giải quyết vấn đề này một cách hiệu quả mà không cần một công tắc liên tục kiểm tra mọi trạng thái với mọi trạng thái mới không?

Việc kiểm tra 2 trạng thái khác nhau là tương đối dễ dàng, nhưng nếu tồn tại trạng thái thứ ba thì không phải là chuyện nhỏ.


Tôi không hiểu tại sao bạn nghĩ trạng thái thứ 3 làm cho nó không tầm thường vì nó đơn giản như việc kiểm tra 2. Bạn có thể đăng một ví dụ về cách bạn hiện đang làm và một ví dụ sử dụng 3 trạng thái.
Giăng

Có lẽ bạn có thể kiểm tra giải pháp tốt nhất để giải quyết khai báo nếu nó có nhiều trạng thái: stackoverflow.com/q/13385744/1077364
vgonisanz

Câu trả lời:


6

Khi tôi cần sử dụng cờ tôi thường làm gì đó dọc theo những dòng này.

enum obj_state
{
    NORMAL      = 0x00000;
    DRY         = 0x00002;
    HOT         = 0x00004;
    BURNING     = 0x00008;
    WET         = 0x00010;
    COLD        = 0x00020;
    FROZEN      = 0x00040;
    POISONED    = 0x00080;
};

int objFlags;

void DryOn() { objFlags |= DRY; }
void HotOn() { objFlags |= HOT; }
// etc...

void DryOff() { if (FlagOn(DRY)) objFlags ^= DRY; }
void HotOff() { if (FlagOn(HOT)) objFlags ^= HOT; }
// etc...

bool isDryOn() { return FlagOn(DRY); }
bool isHotOn() { return FlagOn(HOT); }
// etc...


// If the given Bit is on this will return true.
bool FlagOn(obj_state s) { return (objFlags & s) == s; }

// returns -1 if failed, 1 if successful
int apply_cold(Object obj)
{
    if (obj.isWetOn())
    {
        obj.ColdOff();
        obj.WetOff();
        obj.FrozenOn();
    }
    else
        return -1;

    return 1;
}


//---------------------------------
// alt way of doing DryOn and WetOn
// since these conditions can not be
// active at the same time.
void DryOn() 
{ 
    if (isWetOn()) 
        return;
    else
        objFlags |= DRY; 
}

void WetOn() 
{ 
    if (isDryOn())
        return;
    else;
        objFlags |= WET; 
}

Điều này làm cho việc sử dụng chúng cho những thứ như application_cold () rất dễ dàng và rõ ràng bạn có thể xây dựng trong điều kiện trạng thái của mình như khô và ướt.


Có lẽ bạn có thể kiểm tra giải pháp tốt nhất để giải quyết khai báo nếu nó có nhiều trạng thái: stackoverflow.com/q/13385744/1077364
vgonisanz

7

Hai quan sát:

  1. Hệ thống điều kiện của bạn dường như có hai trục trực giao: nhiệt độ và chất độc. Đại diện cho họ như vậy.
  2. Khi nghĩ về điều này, bạn nên tách các chuyển tiếp từ các trạng thái . COLDHOTlà sự chuyển tiếp theo cách bạn đề cập đến chúng, không phải là trạng thái.

Kết hợp những quan sát đó sẽ dẫn đến một cái gì đó như thế này:

// These is the representation of the two axes.
int temperature; // can be between -2 and +2, 0 is normal, 1 is hot, 2 is burning, -1 is cold, -2 is frozen
bool poisoned;

// These methods represent state transitions.
void applyHeat() {
    if ( temperature <= 2 ) {
        ++temperature;
    }
}

void applyCold() {
    if ( temperature >= -2 ) {
        --temperature;
    }
}

void applyPoison() {
    poisoned = true;
}

void removePoison() {
    poisoned = false;
}

Vấn đề là, tôi sẽ thêm nhiều trạng thái không trực giao, có thể làm gì? NÓNG là một trạng thái quá, bình thường = 30 ºC, nóng = 70 ºC lạnh = 5 ºC. Nhưng nếu thêm nhiệt và nóng, nó sẽ biến thành đốt cháy.
vgonisanz

Làm thế nào về bạn mô hình nhiệt độ như một giá trị số nguyên tính bằng độ C thay vì một boolean nói "nóng" hoặc "lạnh"?
Philipp

Tất nhiên bạn có thể thêm nhiều trạng thái nhiệt độ, như bạn thấy trong câu trả lời của tôi, tôi thực sự đã đại diện cho trạng thái nóng. Những gì Philipp nói có nghĩa là xem mọi cấp độ C là một trạng thái, điều đó cũng tốt, mặc dù lưu ý rằng đây có thể không phải là điều bạn muốn từ quan điểm thiết kế trò chơi: mô phỏng nhiều hơn không đòi hỏi phải chơi trò chơi sâu hơn, mỗi lần.
Eric

3

Đại diện cho trạng thái của bạn dưới dạng bitmask như bạn viết, bạn chỉ có thể dịch các mô tả của bạn về các ràng buộc thành mã:

if ( (state & HOT) && (state & COLD) ) {
    state &= ~HOT;
    state &= ~COLD;   // reset both HOT and COLD flags if both are set
}

if ( (state & COLD) && (state & WET) ) {
    state &= ~WET;    // cold items can't be wet
    state |= FROZEN;  // instead, they're frozen
}

if ( (state & HOT) && (state & WET) ) {
    state &= ~WET;    // hot and wet items dry up...
    state &= ~HOT;    // ...and cool down
}

// add other constraints here...

Bạn có thể gói nó thành một makeStateConsistent()cái mà bạn có thể gọi trước khi kiểm tra các bit trạng thái để đảm bảo rằng trạng thái có ý nghĩa.

Tuy nhiên, một hạn chế của phương pháp này là nó không thể giải thích được thứ tự thay đổi trạng thái. Ví dụ: nếu bạn muốn có một kết quả khác đối với các mặt hàng nóng bị ướt hơn so với các mặt hàng ướt trở nên nóng, bạn không thể làm như thế này: tất cả các makeStateConsistent()phương pháp nhìn thấy là một vật nóng và ướt, không có thông tin về cách nó phải là như vậy

Thay vào đó, những gì bạn có thể làm là làm cho tình trạng mục tin (ít nhất là theo lý thuyết) và vận dụng nó thông qua một tập hợp các phương pháp như coolItem(), heatItem(), wetItem(), dryItem()và vân vân. Bằng cách đó, bản thân các phương pháp thay đổi trạng thái có thể xử lý bất kỳ thay đổi bổ sung nào. Ví dụ, heatItem()phương thức có thể trông giống như thế này:

if ( state & COLD ) {
    state &= ~COLD;    // cold items become normal temp when heated
    if ( state & FROZEN ) {
        state &= ~FROZEN;  // ...and melt if they were frozen
        state |= WET;
    }
} else if ( state & WET ) {
    state &= ~WET;    // wet items dry up when heated, stay normal temp
} else {
    state |= HOT;     // dry normal temp items become hot
}

Tất nhiên, bạn vẫn có thể muốn có một makeStateConsistent()phương thức như một bản sao lưu, chỉ trong trường hợp bạn có một lỗi trong các phương thức thay đổi trạng thái của bạn.

Ngoài ra, trong một số trường hợp, bạn có thể đơn giản hóa mã của mình bằng cách loại bỏ các trạng thái không cần thiết. Ví dụ, bạn có thực sự cần một FROZENtrạng thái riêng biệt , hoặc nó sẽ đủ để chỉ coi bất kỳ vật phẩm lạnh và ướt nào là đông lạnh?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.